This commit is contained in:
Mikhalkovich Stanislav 2026-02-02 22:57:36 +03:00
commit 10d452921c
18 changed files with 909 additions and 807 deletions

View file

@ -62,11 +62,13 @@
%left SHL SHR
%left PLUS MINUS
%left STAR DIVIDE SLASHSLASH PERCENTAGE
%right STARSTAR
%right UMINUS UPLUS
%left BINNOT
%right STARSTAR
%type <id> ident func_name_ident type_decl_identifier
%type <ex> extended_expr expr dotted_ident proc_func_call const_value variable optional_condition act_param extended_new_expr new_expr is_expr variable_as_type
%type <ex> extended_expr expr dotted_ident proc_func_call const_value variable optional_condition act_param new_expr is_expr variable_as_type
%type <stn> act_param_list optional_act_param_list proc_func_decl return_stmt break_stmt continue_stmt global_stmt pass_stmt
%type <stn> var_stmt assign_stmt if_stmt stmt proc_func_call_stmt while_stmt for_stmt optional_else optional_elif exit_stmt
%type <stn> expr_list
@ -77,7 +79,7 @@
%type <stn> import_clause template_type_params template_param_list parts stmt_or_expression expr_mapping_list
%type <ob> optional_semicolon end_of_line variable_list
%type <op> assign_type
%type <ex> expr_mapping
%type <ex> expr_mapping
%type <ex> list_constant set_constant dict_constant generator_object generator_object_for_dict
%type <ex> tuple_expr assign_right_part turbo_tuple_expr
@ -142,25 +144,16 @@ parts
extended_expr
: expr
{
$$ = $1;
}
| extended_new_expr
{
$$ = $1;
}
;
extended_new_expr
: new_expr
{
$$ = $1;
}
// вызов конструктора без скобочек
| NEW type_ref
{
$$ = new new_expr($2, null, false, null, @$);
}
;
type_decl_identifier
: ident
@ -557,7 +550,11 @@ expr
// $$ = new bin_expr($1, $4, Operators.NotIn, @$);
$$ = new un_expr(new bin_expr($1, $4, Operators.In, @$),Operators.LogicalNOT,@$);
}
| MINUS expr
| PLUS expr %prec UPLUS
{
$$ = new un_expr($2, $1.type, @$);
}
| MINUS expr %prec UMINUS
{
$$ = new un_expr($2, $1.type, @$);
}
@ -956,7 +953,7 @@ type_ref
}
| template_type
{
$$ = $1;
$$ = $1;
}
;

View file

@ -1,4 +1,4 @@
cls
..\..\..\Utils\GPLex_GPPG\Gplex.exe /unicode SPythonLexer.lex
..\..\..\Utils\GPLex_GPPG\Gppg.exe /no-lines /gplex SPythonParser.y
..\..\..\Utils\GPLex_GPPG\Gppg.exe /verbose /no-lines /gplex SPythonParser.y
pause

View file

@ -1,4 +1,5 @@
using PascalABCCompiler.Errors;
using PascalABCCompiler;
using PascalABCCompiler.Errors;
using PascalABCCompiler.SemanticTree;
using PascalABCCompiler.SyntaxTree;
using PascalABCCompiler.SystemLibrary;
@ -6,6 +7,8 @@ using PascalABCCompiler.TreeConverter;
using PascalABCCompiler.TreeRealization;
using System;
using System.Collections.Generic;
using System.Linq;
using static PascalABCCompiler.StringConstants;
namespace SPythonSyntaxTreeVisitor
{
@ -241,7 +244,7 @@ namespace SPythonSyntaxTreeVisitor
}
break;*/
case Operators.Division:
if (left.type == right.type && left.type.name == "string")
if (left.type == right.type && left.type.name == string_type_name)
{
var mcn = new method_call(new dot_node(new semantic_addr_value(left, left.location), new ident("IndexOf")),
new expression_list(new semantic_addr_value(right, right.location)), _bin_expr.source_context);
@ -250,26 +253,37 @@ namespace SPythonSyntaxTreeVisitor
}
break;
case Operators.IntegerDivision:
if (left.type == right.type && left.type.name == "real")
var possibleTypes = new string[] { integer_type_name, real_type_name, biginteger_type_name };
var possibleCombinations = possibleTypes.SelectMany(t => possibleTypes, (t1, t2) => Tuple.Create(t1, t2))
.Where(tt => !tt.Equals(Tuple.Create(real_type_name, biginteger_type_name))
&& !tt.Equals(Tuple.Create(biginteger_type_name, real_type_name)));
if (possibleCombinations.Contains(Tuple.Create(left.type.name, right.type.name)))
{
var exprlist = new expression_list(); exprlist.source_context = _bin_expr.source_context;
exprlist.Add(new semantic_addr_value(left, left.location));
exprlist.Add(new semantic_addr_value(right, right.location));
var floornode = new method_call(new ident("!FloorDiv"), exprlist, _bin_expr.source_context);
var floornode = new method_call(new ident("!Div"), exprlist, _bin_expr.source_context);
visit(floornode);
return;
}
break;
case Operators.ModulusRemainder:
if (left.type == right.type && left.type.name == "real")
possibleTypes = new string[] { integer_type_name, real_type_name, biginteger_type_name };
possibleCombinations = possibleTypes.SelectMany(t => possibleTypes, (t1, t2) => Tuple.Create(t1, t2))
.Where(tt => !tt.Equals(Tuple.Create(real_type_name, biginteger_type_name))
&& !tt.Equals(Tuple.Create(biginteger_type_name, real_type_name)));
if (possibleCombinations.Contains(Tuple.Create(left.type.name, right.type.name)))
{
//var divnode = new bin_expr(new semantic_addr_value(left, left.location), new semantic_addr_value(right, right.location), Operators.IntegerDivision, _bin_expr.source_context);
//var multnode = new bin_expr(new semantic_addr_value(right, right.location), divnode, Operators.Multiplication);
//var modnode = new bin_expr(new semantic_addr_value(left, left.location), multnode, Operators.Minus);
var exprlist = new expression_list(); exprlist.source_context = _bin_expr.source_context;
exprlist.Add(new semantic_addr_value(left, left.location));
exprlist.Add(new semantic_addr_value(right, right.location));
var modnode = new method_call(new ident("!FloorMod"), exprlist, _bin_expr.source_context);
var modnode = new method_call(new ident("!Mod"), exprlist, _bin_expr.source_context);
visit(modnode);
return;
}

View file

@ -32,7 +32,7 @@ namespace Languages.SPython.Frontend.Converters
public override void visit(tuple_node tup)
{
var dn = new ident("CreateTuple", tup.source_context);
var dn = new ident("!CreateTuple", tup.source_context);
var mc = new method_call(dn, tup.el, tup.source_context);
//var sug = new sugared_expression(tup, mc, tup.source_context); - нет никакой семантической проверки - всё - на уровне синтаксиса!

View file

@ -7,7 +7,7 @@ namespace Languages.SPython.Frontend.Converters
{
public HashSet<string> variablesUsedAsGlobal = new HashSet<string>();
public NameCorrectVisitor(Dictionary<string, Dictionary<string, bool>> namesFromUsedUnits, HashSet<string> definedFunctionsNames) : base(namesFromUsedUnits)
public NameCorrectVisitor(string unitName, Dictionary<string, Dictionary<string, bool>> namesFromUsedUnits, HashSet<string> definedFunctionsNames) : base(unitName, namesFromUsedUnits)
{
foreach (string definedFunctionName in definedFunctionsNames)
{
@ -104,22 +104,31 @@ namespace Languages.SPython.Frontend.Converters
}
}
// функция нужна для классов list, dict и set из-за наличия одноименных функций в другом модуле
public override void visit(template_type_reference _template_type_reference)
{
named_type_reference _named_type_reference = _template_type_reference.name;
string name = _named_type_reference.names[0].name;
string name = _named_type_reference.names[0].name + '`';
string fullName = name + $"`{_template_type_reference.params_list.Count}";
NameKind nameKind = symbolTable[name];
NameKind nameKind = symbolTable[fullName];
// синонимы типов без '`'
if (nameKind == NameKind.Unknown)
{
name = name.TrimEnd('`');
nameKind = symbolTable[name];
}
switch (nameKind)
{
case NameKind.ModuleAlias:
_named_type_reference.names[0].name = symbolTable.AliasToRealName(name);
break;
case NameKind.ImportedVariableAlias:
case NameKind.ImportedNotVariableAlias:
_named_type_reference.names.Insert(0, new ident(symbolTable.AliasToModuleName(fullName), _named_type_reference.names[0].source_context));
_named_type_reference.names[1].name = symbolTable.AliasToRealName(fullName);
_named_type_reference.names.Insert(0, new ident(symbolTable.AliasToModuleName(name), _named_type_reference.names[0].source_context));
_named_type_reference.names[1].name = symbolTable.AliasToRealName(name);
break;
case NameKind.Unknown:

View file

@ -75,7 +75,8 @@ namespace Languages.SPython.Frontend.Converters
// проверка корректности имён, разрешение неоднозначности
// сохранение множества переменных, использующихся как глобальные в ncv.variablesUsedAsGlobal
var ncv = new NameCorrectVisitor(compilationArtifacts.NamesFromUsedUnits, ffv.definedFunctionsNames);
var ncv = new NameCorrectVisitor(System.IO.Path.GetFileNameWithoutExtension(((compilation_unit)root).file_name),
compilationArtifacts.NamesFromUsedUnits, ffv.definedFunctionsNames);
if (!new TryCatchDecorator(ncv, forIntellisense).ProcessNode(root))
return root;

View file

@ -3,6 +3,7 @@ using PascalABCCompiler.Parsers;
using PascalABCCompiler.SyntaxTree;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Languages.SPython.Frontend.Converters
{
@ -13,8 +14,8 @@ namespace Languages.SPython.Frontend.Converters
private readonly ILanguageInformation languageInformation = Facade.LanguageProvider.Instance.SelectLanguageByName("SPython").LanguageInformation;
public SymbolTableFillingVisitor(Dictionary<string, Dictionary<string, bool>> par) {
symbolTable = new SymbolTable(par);
public SymbolTableFillingVisitor(string unitName, Dictionary<string, Dictionary<string, bool>> par) {
symbolTable = new SymbolTable(unitName, par);
}
// нужны методы из BaseChangeVisitor, но порядок обхода из WalkingVisitorNew
@ -169,18 +170,22 @@ namespace Languages.SPython.Frontend.Converters
{
foreach (var kv in symbolTable.ModuleNameToSymbols[module_name])
symbolTable.AddAlias(kv.Key, kv.Value, kv.Key, module_name);
}
}
else
{
foreach (as_statement as_Statement in _from_import_statement.imported_names.as_statements)
{
var namesDict = symbolTable.ModuleNameToSymbols[module_name];
if (!namesDict.ContainsKey(as_Statement.real_name.name))
// Учитываем, что в именах может быть обозначение шаблонности
var foundName = namesDict.FirstOrDefault(kv => !kv.Key.Contains('`') && kv.Key == as_Statement.real_name.name
|| kv.Key.Contains('`') && kv.Key.Substring(0, kv.Key.IndexOf('`')) == as_Statement.real_name.name).Key;
if (foundName == null)
throw new SPythonSyntaxVisitorError("MODULE_{0}_HAS_NO_NAME_{1}",
_from_import_statement.source_context, module_real_name, as_Statement.real_name.name);
symbolTable.AddAlias(as_Statement.real_name.name, namesDict[as_Statement.real_name.name], as_Statement.alias.name, module_name);
symbolTable.AddAlias(as_Statement.real_name.name, namesDict[foundName], as_Statement.alias.name, module_name);
}
}
}
@ -226,7 +231,7 @@ namespace Languages.SPython.Frontend.Converters
private readonly HashSet<string> forwardDeclaredFunctions = new HashSet<string>();
private readonly string[] Keywords = {
"int", "float", "str", "bool", "tuple", // standard types
"int", "float", "str", "bool", "bigint", // standard types
"break", "continue", "exit", "halt", // standard ops
"true", "false", // constants
};
@ -237,13 +242,15 @@ namespace Languages.SPython.Frontend.Converters
currentScope.Add(keyword, NameKind.Keyword);
}
public SymbolTable(Dictionary<string, Dictionary<string, bool>> par)
public SymbolTable(string unitName, Dictionary<string, Dictionary<string, bool>> par)
{
ModuleNameToSymbols = par;
entryScope = new LocalScope();
currentScope = entryScope;
FillKeywords();
AddAliasesFromStandartLibraries();
if (!StandardLibraries.Contains(unitName))
AddAliasesFromStandartLibraries();
}
// names added to current function with global statements
@ -346,7 +353,18 @@ namespace Languages.SPython.Frontend.Converters
}
public void AddAlias(string realName, bool isVariable, string alias, string moduleName)
{
{
// оставляем только обозначение шаблонности
if (alias.Contains("`"))
{
alias = alias.Substring(0, alias.IndexOf('`') + 1);
}
// в realName не должно быть обозначения шаблонности, потому что оно пойдет в синтаксический узел
if (realName.Contains("`"))
{
realName = realName.Substring(0, realName.IndexOf('`'));
}
entryScope.Add(alias, realName, isVariable ? NameKind.ImportedVariableAlias : NameKind.ImportedNotVariableAlias, moduleName);
}

View file

@ -23,7 +23,7 @@ namespace Languages.SPython.Frontend.Converters
throw new SPythonSyntaxVisitorError("LONG_TUPLE_TYPENAME",
ttr.source_context, cnt);
}
ttr.name.names[index].name += cnt;
ttr.name.names[index].name = "!tuple" + cnt;
}
base.visit(ttr);

View file

@ -2692,13 +2692,17 @@ namespace CodeCompletion
}
}
// Далее импортирумые пользовательские модули компилируются в обратном порядке, стандартные модули в порядке описания
List<string> usedUnitsNames = new List<string>();
interface_node _interface_node = _unit_module.interface_part;
if (_interface_node.uses_modules != null)
{
usedUnitsNames = _interface_node.uses_modules.units.Select(unit => unit.name.idents[0].name).ToList();
usedUnitsNames = _interface_node.uses_modules.units
.Where(unit => unit.name.idents.Count == 1)
.Select(unit => unit.name.idents[0].name).ToList();
(cur_scope as InterfaceUnitScope).uses_source_range = get_location(_interface_node.uses_modules);
@ -2714,7 +2718,7 @@ namespace CodeCompletion
// компиляция зависимостей из конструкций import и from import
if (cur_scope != null && _unit_module.initialization_part != null)
{
CompileImportedDependencies(_unit_module.initialization_part, _unit_module.file_name, ns_cache, usedUnitsNames, currentUnitLanguage);
CompileImportedDependencies(_unit_module.initialization_part, cur_scope, _unit_module.file_name, ns_cache, currentUnitLanguage);
}
StringComparer comparer = currentUnitLanguage.CaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
@ -3046,6 +3050,8 @@ namespace CodeCompletion
{
try
{
var comparer = currentUnitLanguage.CaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
// на случай имен модулей, отличающихся от имен файла EVA
string realName = GetRealNameForModule(importedName);
@ -3060,7 +3066,7 @@ namespace CodeCompletion
if (dc.visitor != null)
{
dc.visitor.entry_scope.InitAssemblies();
AddImportedNamesToCurScope(importStatement, asStatementsList, cur_scope, importedName, dc.visitor.entry_scope);
AddImportedNamesToCurScope(importStatement, asStatementsList, cur_scope, importedName, dc.visitor.entry_scope, comparer);
}
}
else
@ -3072,7 +3078,7 @@ namespace CodeCompletion
IntellisensePCUReader pcu_rdr = new IntellisensePCUReader();
SymScope ss = pcu_rdr.GetUnit(unit_name);
UnitDocCache.Load(ss, unit_name);
AddImportedNamesToCurScope(importStatement, asStatementsList, cur_scope, importedName, ss);
AddImportedNamesToCurScope(importStatement, asStatementsList, cur_scope, importedName, ss, comparer);
}
}
@ -3086,17 +3092,17 @@ namespace CodeCompletion
}
}
private static void AddImportedNamesToCurScope(statement importStatement, as_statement_list asStatementsList, SymScope currentScope, string importedModuleName, SymScope importedModuleScope)
private static void AddImportedNamesToCurScope(statement importStatement, as_statement_list asStatementsList, SymScope currentScope, string importedModuleName, SymScope importedModuleScope, StringComparison comparer)
{
int fictiveUnitIndex = currentScope.used_units.FindIndex(unit => unit.Name == importedModuleName);
SymScope fictiveUnit = fictiveUnitIndex > -1 ? currentScope.used_units[fictiveUnitIndex] : null;
if (importStatement is import_statement import)
{
int fictiveUnitIndex = currentScope.used_units.FindIndex(unit => unit.Name.Equals(importedModuleName + "?ModuleName", comparer));
SymScope fictiveUnit = fictiveUnitIndex > -1 ? currentScope.used_units[fictiveUnitIndex] : null;
if (fictiveUnit == null)
{
fictiveUnit = new InterfaceUnitScope(new SymInfo(importedModuleName, SymbolKind.Namespace, ""), null);
fictiveUnit = new InterfaceUnitScope(new SymInfo(importedModuleName + "?ModuleName", SymbolKind.Namespace, ""), null);
currentScope.AddUsedUnit(fictiveUnit);
}
@ -3112,6 +3118,10 @@ namespace CodeCompletion
}
else if (importStatement is from_import_statement fromImport)
{
int fictiveUnitIndex = currentScope.used_units.FindIndex(unit => unit.Name.Equals(importedModuleName, comparer));
SymScope fictiveUnit = fictiveUnitIndex > -1 ? currentScope.used_units[fictiveUnitIndex] : null;
if (fromImport.is_star)
{
if (fictiveUnit != null)
@ -3270,11 +3280,15 @@ namespace CodeCompletion
}
}
// Далее импортирумые пользовательские модули компилируются в обратном порядке, стандартные модули в порядке описания
List<string> usedUnitsNames = new List<string>();
if (_program_module.used_units != null)
{
usedUnitsNames = _program_module.used_units.units.Select(unit => unit.name.idents[0].name).ToList();
usedUnitsNames = _program_module.used_units.units
.Where(unit => unit.name.idents.Count == 1)
.Select(unit => unit.name.idents[0].name).ToList();
unit_scope.uses_source_range = get_location(_program_module.used_units);
@ -3290,7 +3304,7 @@ namespace CodeCompletion
// компиляция зависимостей из конструкций import и from import
if (cur_scope != null && _program_module.program_block.program_code != null)
{
CompileImportedDependencies(_program_module.program_block.program_code, _program_module.file_name, ns_cache, usedUnitsNames, currentUnitLanguage);
CompileImportedDependencies(_program_module.program_block.program_code, cur_scope, _program_module.file_name, ns_cache, currentUnitLanguage);
}
StringComparer comparer = currentUnitLanguage.CaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
@ -3361,7 +3375,7 @@ namespace CodeCompletion
}
}
private void CompileImportedDependencies(statement_list statementList, string fileName, Hashtable ns_cache, List<string> usedUnitNames, Languages.Facade.ILanguage currentUnitLanguage)
private void CompileImportedDependencies(statement_list statementList, SymScope cur_scope, string fileName, Hashtable ns_cache, Languages.Facade.ILanguage currentUnitLanguage)
{
var importStatements = statementList.list.Where(st => st is import_statement || st is from_import_statement);
@ -3374,17 +3388,20 @@ namespace CodeCompletion
CompileImportedUnit(unitNode.name, import, import.modules_names,
Path.GetDirectoryName(fileName),
cur_scope, unl, currentUnitLanguage);
usedUnitNames.Add(unitNode.name);
}
}
else if (importStatement is from_import_statement fromImport)
{
CompileImportedUnit(fromImport.module_name.name, fromImport, fromImport.imported_names,
Path.GetDirectoryName(fileName),
cur_scope, unl, currentUnitLanguage);
var comparer = currentUnitLanguage.CaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
usedUnitNames.Add(fromImport.module_name.name);
// Стандартные модули подсоединятся автоматически (import в другой ветке в любом случае нужен)
if (currentUnitLanguage.SystemUnitNames.Contains(cur_scope.Name, comparer)
|| !currentUnitLanguage.SystemUnitNames.Contains(fromImport.module_name.name, comparer))
{
CompileImportedUnit(fromImport.module_name.name, fromImport, fromImport.imported_names,
Path.GetDirectoryName(fileName),
cur_scope, unl, currentUnitLanguage);
}
}
}
}

View file

@ -775,10 +775,10 @@ namespace CodeCompletion
if (members == null) return null;
//if (loc != null && loc.begin_line_num <= line && loc.end_line_num >= line && loc.begin_column_num <= column && loc.end_column_num >= column)
if (IsInScope(loc, line, column))
res = this;
minScope = res = this;
TypeScope ts = this as TypeScope;
if (res == null && ts != null && ts.predef_loc != null && IsInScope(ts.predef_loc, line, column))
res = this;
minScope = res = this;
foreach (SymScope ss in members)
if (this != ss && this.topScope != ss && ss.loc != null && (loc == null || loc != null && loc.file_name != null && ss.loc.file_name == loc.file_name))
{

View file

@ -64,6 +64,7 @@ namespace Languages.Facade
/// <summary>
/// Названия системных модулей (стандартной библиотеки и др.)
/// Компилируются в порядке добавления в список
/// </summary>
string[] SystemUnitNames { get; }

View file

@ -107,6 +107,7 @@ namespace PascalABCCompiler
public static readonly string uint_type_name = "longword";//cardinal
public static readonly string long_type_name = "int64";//int64
public static readonly string ulong_type_name = "uint64";
public static readonly string biginteger_type_name = "BigInteger";
//public static readonly string decimal_type_name = "decimal";
public static readonly string real_type_name = "real";
public static readonly string float_type_name = "single";

View file

@ -1,5 +1,6 @@
from PABCSystem import Object as obj, Write as pas_print
from SPythonSystem import range, len
from SPythonSystem import range, len, tuple
from SPythonHidden import *
def print(*args: obj, **kwargs: str):
sep: str = ' '
@ -17,5 +18,11 @@ def print(*args: obj, **kwargs: str):
pas_print(args[len(args) - 1])
pas_print(end)
#def divmod(a: int, b: int) -> (int,int)
# := (a // b, a % b);
def divmod(a: int, b: int) -> tuple[int, int]:
return (a // b, a % b)
def divmod(a: float, b: float) -> tuple[float, float]:
return (a // b, a % b)
def divmod(a: bigint, b: bigint) -> tuple[bigint, bigint]:
return (a // b, a % b)

View file

@ -0,0 +1,9 @@
# Использование кортежей
a,b = divmod(-7, 3)
temp = divmod(-7, 3)
t: tuple[int, int] = divmod(-7, 3)
t1: tuple[int] = tuple.Create(0) # из одного эл-та пока так
print(a == t.Item1)
print(b == t.Item2)

View file

@ -7,9 +7,17 @@ uses SPythonSystem;
function !Floor(x : real) : integer;
function !FloorDiv(x: real; y: real): integer;
function !Div(x: integer; y: integer): integer;
function !FloorMod(x: real; y: real): real;
function !Div(x: BigInteger; y: BigInteger): BigInteger;
function !Div(x: real; y: real): real;
function !Mod(x: integer; y: integer): integer;
function !Mod(x: BigInteger; y: BigInteger): BigInteger;
function !Mod(x: real; y: real): real;
type !UnknownType = class
end;
@ -46,8 +54,26 @@ function dict<TKey, TVal>(seqOfPairs: sequence of (TKey, TVal)): dict<TKey, TVal
function !Floor(x : real) : integer := PABCSystem.Floor(x);
function !FloorDiv(x: real; y: real): integer := PABCSystem.Floor(x / y);
function !Div(x: integer; y: integer): integer;
begin
Result := x div y;
if ((x < 0) xor (y < 0)) and (x mod y <> 0) then
Result -= 1;
end;
function !FloorMod(x: real; y: real): real := x - PABCSystem.Floor(x / y) * y;
function !Div(x: BigInteger; y: BigInteger): BigInteger;
begin
Result := x div y;
if ((x < 0) xor (y < 0)) and (x mod y <> 0) then
Result -= 1;
end;
function !Div(x: real; y: real): real := System.Math.Floor(x / y);
function !Mod(x: integer; y: integer): integer := x - !Div(x, y) * y;
function !Mod(x: BigInteger; y: BigInteger): BigInteger := x - !Div(x, y) * y;
function !Mod(x: real; y: real): real := x - PABCSystem.Floor(x / y) * y;
end.

View file

@ -99,9 +99,6 @@ function abs(x: integer): integer;
/// Возвращает абсолютное значение числа
function abs(x: real): real;
/// Возвращает результат и остаток от целочисленного деления
function divmod(a,b: integer): (integer,integer);
/// Возвращает x в степени y
function pow(x,y: real): real;
/// Возвращает x в целой степени n
@ -522,27 +519,30 @@ function !pow_recursion(x, n: integer): integer;
function !pow_recursion(x, n: biginteger): biginteger;
// TUPLES BEGIN
function CreateTuple<T1, T2>(
function !CreateTuple<T>(v: T): System.Tuple<T>;
function !CreateTuple<T1, T2>(
v1: T1; v2: T2
): System.Tuple<T1, T2>;
function CreateTuple<T1, T2, T3>(
function !CreateTuple<T1, T2, T3>(
v1: T1; v2: T2; v3: T3
): System.Tuple<T1, T2, T3>;
function CreateTuple<T1, T2, T3, T4>(
function !CreateTuple<T1, T2, T3, T4>(
v1: T1; v2: T2; v3: T3; v4: T4
): System.Tuple<T1, T2, T3, T4>;
function CreateTuple<T1, T2, T3, T4, T5>(
function !CreateTuple<T1, T2, T3, T4, T5>(
v1: T1; v2: T2; v3: T3; v4: T4; v5: T5
): System.Tuple<T1, T2, T3, T4, T5>;
function CreateTuple<T1, T2, T3, T4, T5, T6>(
function !CreateTuple<T1, T2, T3, T4, T5, T6>(
v1: T1; v2: T2; v3: T3; v4: T4; v5: T5; v6: T6
): System.Tuple<T1, T2, T3, T4, T5, T6>;
function CreateTuple<T1, T2, T3, T4, T5, T6, T7>(
function !CreateTuple<T1, T2, T3, T4, T5, T6, T7>(
v1: T1; v2: T2; v3: T3; v4: T4; v5: T5; v6: T6; v7: T7
): System.Tuple<T1, T2, T3, T4, T5, T6, T7>;
@ -550,12 +550,14 @@ function CreateTuple<T1, T2, T3, T4, T5, T6, T7>(
type
biginteger = PABCSystem.BigInteger;
tuple2<T1, T2> = System.Tuple<T1, T2>;
tuple3<T1, T2, T3> = System.Tuple<T1, T2, T3>;
tuple4<T1, T2, T3, T4> = System.Tuple<T1, T2, T3, T4>;
tuple5<T1, T2, T3, T4, T5> = System.Tuple<T1, T2, T3, T4, T5>;
tuple6<T1, T2, T3, T4, T5, T6> = System.Tuple<T1, T2, T3, T4, T5, T6>;
tuple7<T1, T2, T3, T4, T5, T6, T7> = System.Tuple<T1, T2, T3, T4, T5, T6, T7>;
tuple = System.Tuple;
!tuple1<T> = System.Tuple<T>;
!tuple2<T1, T2> = System.Tuple<T1, T2>;
!tuple3<T1, T2, T3> = System.Tuple<T1, T2, T3>;
!tuple4<T1, T2, T3, T4> = System.Tuple<T1, T2, T3, T4>;
!tuple5<T1, T2, T3, T4, T5> = System.Tuple<T1, T2, T3, T4, T5>;
!tuple6<T1, T2, T3, T4, T5, T6> = System.Tuple<T1, T2, T3, T4, T5, T6>;
!tuple7<T1, T2, T3, T4, T5, T6, T7> = System.Tuple<T1, T2, T3, T4, T5, T6, T7>;
empty_list = class
class function operator implicit<T>(x: empty_list): list<T>;
@ -668,10 +670,6 @@ end;
function abs(x: integer): integer := if x >= 0 then x else -x;
function abs(x: real): real := PABCSystem.Abs(x);
function divmod(a,b: integer): (integer,integer)
:= (a div b, a mod b);
// divmod вещественный аналог надо реализовать на питоне бы
function pow(x,y: real): real := PABCSystem.Power(x,y);
function pow(x: real; n: integer): real := PABCSystem.Power(x,n);
@ -777,32 +775,35 @@ function get_keys<K, V>(dct: Dictionary<K, V>):= dct.keys;
function get_values<K, V>(dct: Dictionary<K, V>):= dct.values;
// TUPLES BEGIN
function CreateTuple<T1, T2>(
function !CreateTuple<T>(v: T): System.Tuple<T> := Tuple.Create(v);
function !CreateTuple<T1, T2>(
v1: T1; v2: T2
): System.Tuple<T1, T2>
:= (v1, v2);
function CreateTuple<T1, T2, T3>(
function !CreateTuple<T1, T2, T3>(
v1: T1; v2: T2; v3: T3
): System.Tuple<T1, T2, T3>
:= (v1, v2, v3);
function CreateTuple<T1, T2, T3, T4>(
function !CreateTuple<T1, T2, T3, T4>(
v1: T1; v2: T2; v3: T3; v4: T4
): System.Tuple<T1, T2, T3, T4>
:= (v1, v2, v3, v4);
function CreateTuple<T1, T2, T3, T4, T5>(
function !CreateTuple<T1, T2, T3, T4, T5>(
v1: T1; v2: T2; v3: T3; v4: T4; v5: T5
): System.Tuple<T1, T2, T3, T4, T5>
:= (v1, v2, v3, v4, v5);
function CreateTuple<T1, T2, T3, T4, T5, T6>(
function !CreateTuple<T1, T2, T3, T4, T5, T6>(
v1: T1; v2: T2; v3: T3; v4: T4; v5: T5; v6: T6
): System.Tuple<T1, T2, T3, T4, T5, T6>
:= (v1, v2, v3, v4, v5, v6);
function CreateTuple<T1, T2, T3, T4, T5, T6, T7>(
function !CreateTuple<T1, T2, T3, T4, T5, T6, T7>(
v1: T1; v2: T2; v3: T3; v4: T4; v5: T5; v6: T6; v7: T7
): System.Tuple<T1, T2, T3, T4, T5, T6, T7>
:= (v1, v2, v3, v4, v5, v6, v7);

View file

@ -1,5 +1,6 @@
from PABCSystem import Object as obj, Write as pas_print
from SPythonSystem import range, len
from SPythonSystem import range, len, tuple
from SPythonHidden import *
def print(*args: obj, **kwargs: str):
sep: str = ' '
@ -17,5 +18,11 @@ def print(*args: obj, **kwargs: str):
pas_print(args[len(args) - 1])
pas_print(end)
#def divmod(a: int, b: int) -> (int,int)
# := (a // b, a % b);
def divmod(a: int, b: int) -> tuple[int, int]:
return (a // b, a % b)
def divmod(a: float, b: float) -> tuple[float, float]:
return (a // b, a % b)
def divmod(a: bigint, b: bigint) -> tuple[bigint, bigint]:
return (a // b, a % b)