├── .gitattributes ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── compiler ├── __init__.py ├── astnodes │ ├── __init__.py │ ├── assignstmt.py │ ├── binaryexpr.py │ ├── booleanliteral.py │ ├── callexpr.py │ ├── classdef.py │ ├── classtype.py │ ├── compilererror.py │ ├── declaration.py │ ├── errors.py │ ├── expr.py │ ├── exprstmt.py │ ├── forstmt.py │ ├── funcdef.py │ ├── globaldecl.py │ ├── identifier.py │ ├── ifexpr.py │ ├── ifstmt.py │ ├── indexexpr.py │ ├── integerliteral.py │ ├── listexpr.py │ ├── listtype.py │ ├── literal.py │ ├── memberexpr.py │ ├── methodcallexpr.py │ ├── node.py │ ├── noneliteral.py │ ├── nonlocaldecl.py │ ├── program.py │ ├── returnstmt.py │ ├── stmt.py │ ├── stringliteral.py │ ├── typeannotation.py │ ├── typedvar.py │ ├── unaryexpr.py │ ├── vardef.py │ └── whilestmt.py ├── builder.py ├── cil_backend.py ├── closuretransformer.py ├── closurevisitor.py ├── compiler.py ├── empty_list_typer.py ├── jvm_backend.py ├── llvm_backend.py ├── nestedfunchoister.py ├── parser.py ├── python_backend.py ├── typechecker.py ├── typeeraser.py ├── types │ ├── Types.py │ ├── __init__.py │ ├── classvaluetype.py │ ├── functype.py │ ├── listvaluetype.py │ ├── symboltype.py │ ├── valuetype.py │ └── varinstance.py ├── typesystem.py ├── varcollector.py ├── visitor.py └── wasm_backend.py ├── demo_cil.sh ├── demo_jvm.sh ├── demo_llvm.sh ├── demo_wasm.sh ├── main.py ├── pyrightconfig.json ├── test.py ├── tests ├── parse │ ├── bad_annotation.py │ ├── bad_assign_expr1.py │ ├── bad_assign_expr2.py │ ├── bad_decl_location.py │ ├── bad_decl_location2.py │ ├── bad_decl_location3.py │ ├── bad_func_def.py │ ├── bad_indentation.py │ ├── bad_inheritance.py │ ├── bad_inner_class.py │ ├── bad_inner_class2.py │ ├── bad_keywords.py │ ├── bad_literal.py │ ├── bad_missing_annotation.py │ ├── bad_slice.py │ ├── bad_stmt.py │ ├── bad_var_decl.py │ ├── bad_var_decl2.py │ ├── bad_while_else.py │ ├── chained_mixed_assignments.py │ ├── chained_mixed_assignments.py.ast │ ├── chained_var_assignments.py │ ├── chained_var_assignments.py.ast │ ├── class_attr.py │ ├── class_attr.py.ast │ ├── class_attr_get.py │ ├── class_attr_get.py.ast │ ├── class_attr_set.py │ ├── class_attr_set.py.ast │ ├── class_constructor.py │ ├── class_constructor.py.ast │ ├── class_method.py │ ├── class_method.py.ast │ ├── coverage.py │ ├── coverage.py.ast │ ├── def_func.py │ ├── def_func.py.ast │ ├── def_func_args.py │ ├── def_func_args.py.ast │ ├── def_func_global.py │ ├── def_func_global.py.ast │ ├── def_func_nested.py │ ├── def_func_nested.py.ast │ ├── def_func_nonlocal.py │ ├── def_func_nonlocal.py.ast │ ├── expr_if.py │ ├── expr_if.py.ast │ ├── expr_index.py │ ├── expr_index.py.ast │ ├── expr_plus.py │ ├── expr_plus.py.ast │ ├── expr_unary.py │ ├── expr_unary.py.ast │ ├── global.py │ ├── global.py.ast │ ├── literals.py │ ├── literals.py.ast │ ├── stmt_call.py │ ├── stmt_call.py.ast │ ├── stmt_for.py │ ├── stmt_for.py.ast │ ├── stmt_if.py │ ├── stmt_if.py.ast │ ├── stmt_if_elif.py │ ├── stmt_if_elif.py.ast │ ├── stmt_if_elif_else.py │ ├── stmt_if_elif_else.py.ast │ ├── stmt_ifelse.py │ ├── stmt_ifelse.py.ast │ ├── stmt_list_assign.py │ ├── stmt_list_assign.py.ast │ ├── stmt_while.py │ └── stmt_while.py.ast ├── runtime │ ├── assignment.py │ ├── binary_tree.py │ ├── classes.py │ ├── contains.py │ ├── control_flow.py │ ├── control_flow_2.py │ ├── doubling_vector.py │ ├── exponent.py │ ├── expr_stmt.py │ ├── functions.py │ ├── global_loop.py │ ├── globals.py │ ├── hello_world.py │ ├── incrementing_counter.py │ ├── inherit_init.py │ ├── int_and_bool.py │ ├── int_and_bool_control_flow.py │ ├── int_and_bool_funcs.py │ ├── linked_list.py │ ├── lists.py │ ├── local_loop.py │ ├── modulo.py │ ├── nested_list.py │ ├── nonlocal.py │ ├── nonlocal_builtins.py │ ├── nonlocal_loop.py │ ├── null_and_empty_list_compare.py │ ├── operators.py │ ├── ratio.py │ ├── short_circuit.py │ ├── simple_list.py │ ├── simple_string.py │ ├── strings.py │ └── var_decl.py └── typecheck │ ├── ast_coverage.py │ ├── ast_coverage.py.ast │ ├── ast_coverage.py.ast.typed │ ├── bad_assign_expr.py │ ├── bad_assign_expr.py.ast │ ├── bad_assign_expr.py.ast.typed │ ├── bad_class_attr.py │ ├── bad_class_attr.py.ast │ ├── bad_class_attr.py.ast.typed │ ├── bad_class_attr_type.py │ ├── bad_class_attr_type.py.ast │ ├── bad_class_attr_type.py.ast.typed │ ├── bad_class_init_override.py │ ├── bad_class_init_override.py.ast │ ├── bad_class_init_override.py.ast.typed │ ├── bad_class_init_override2.py │ ├── bad_class_init_override2.py.ast │ ├── bad_class_init_override2.py.ast.typed │ ├── bad_class_init_return.py │ ├── bad_class_init_return.py.ast │ ├── bad_class_init_return.py.ast.typed │ ├── bad_class_member_expr.py │ ├── bad_class_member_expr.py.ast │ ├── bad_class_member_expr.py.ast.typed │ ├── bad_class_method.py │ ├── bad_class_method.py.ast │ ├── bad_class_method.py.ast.typed │ ├── bad_class_method_invoke.py │ ├── bad_class_method_invoke.py.ast │ ├── bad_class_method_invoke.py.ast.typed │ ├── bad_class_method_override.py │ ├── bad_class_method_override.py.ast │ ├── bad_class_method_override.py.ast.typed │ ├── bad_class_method_override_attr.py │ ├── bad_class_method_override_attr.py.ast │ ├── bad_class_method_override_attr.py.ast.typed │ ├── bad_class_super.py │ ├── bad_class_super.py.ast │ ├── bad_class_super.py.ast.typed │ ├── bad_concat.py │ ├── bad_concat.py.ast │ ├── bad_concat.py.ast.typed │ ├── bad_duplicate_class.py │ ├── bad_duplicate_class.py.ast │ ├── bad_duplicate_class.py.ast.typed │ ├── bad_duplicate_class_member.py │ ├── bad_duplicate_class_member.py.ast │ ├── bad_duplicate_class_member.py.ast.typed │ ├── bad_duplicate_global.py │ ├── bad_duplicate_global.py.ast │ ├── bad_duplicate_global.py.ast.typed │ ├── bad_duplicate_global_2.py │ ├── bad_duplicate_global_2.py.ast │ ├── bad_duplicate_global_2.py.ast.typed │ ├── bad_duplicate_global_3.py │ ├── bad_duplicate_global_3.py.ast │ ├── bad_duplicate_global_3.py.ast.typed │ ├── bad_duplicate_local.py │ ├── bad_duplicate_local.py.ast │ ├── bad_duplicate_local.py.ast.typed │ ├── bad_expr_binary.py │ ├── bad_expr_binary.py.ast │ ├── bad_expr_binary.py.ast.typed │ ├── bad_expr_if.py │ ├── bad_expr_if.py.ast │ ├── bad_expr_if.py.ast.typed │ ├── bad_expr_unary.py │ ├── bad_expr_unary.py.ast │ ├── bad_expr_unary.py.ast.typed │ ├── bad_func_def_call.py │ ├── bad_func_def_call.py.ast │ ├── bad_func_def_call.py.ast.typed │ ├── bad_func_def_return.py │ ├── bad_func_def_return.py.ast │ ├── bad_func_def_return.py.ast.typed │ ├── bad_list_assign.py │ ├── bad_list_assign.py.ast │ ├── bad_list_assign.py.ast.typed │ ├── bad_list_index.py │ ├── bad_list_index.py.ast │ ├── bad_list_index.py.ast.typed │ ├── bad_local_assign.py │ ├── bad_local_assign.py.ast │ ├── bad_local_assign.py.ast.typed │ ├── bad_none_assign.py │ ├── bad_none_assign.py.ast │ ├── bad_none_assign.py.ast.typed │ ├── bad_nonlocal_global.py │ ├── bad_nonlocal_global.py.ast │ ├── bad_nonlocal_global.py.ast.typed │ ├── bad_return_missing.py │ ├── bad_return_missing.py.ast │ ├── bad_return_missing.py.ast.typed │ ├── bad_return_top.py │ ├── bad_return_top.py.ast │ ├── bad_return_top.py.ast.typed │ ├── bad_shadow_local.py │ ├── bad_shadow_local.py.ast │ ├── bad_shadow_local.py.ast.typed │ ├── bad_shadow_local_2.py │ ├── bad_shadow_local_2.py.ast │ ├── bad_shadow_local_2.py.ast.typed │ ├── bad_strings.py │ ├── bad_strings.py.ast │ ├── bad_strings.py.ast.typed │ ├── bad_type_annotation.py │ ├── bad_type_annotation.py.ast │ ├── bad_type_annotation.py.ast.typed │ ├── bad_type_id.py │ ├── bad_type_id.py.ast │ ├── bad_type_id.py.ast.typed │ ├── bad_var_assign.py │ ├── bad_var_assign.py.ast │ ├── bad_var_assign.py.ast.typed │ ├── call.py │ ├── call.py.ast.typed │ ├── call_with_args.py │ ├── call_with_args.py.ast.typed │ ├── class_def_assign.py │ ├── class_def_assign.py.ast │ ├── class_def_assign.py.ast.typed │ ├── class_def_attr.py │ ├── class_def_attr.py.ast │ ├── class_def_attr.py.ast.typed │ ├── class_def_init.py │ ├── class_def_init.py.ast │ ├── class_def_init.py.ast.typed │ ├── class_def_methods.py │ ├── class_def_methods.py.ast │ ├── class_def_methods.py.ast.typed │ ├── decl_global_forward.py │ ├── decl_global_forward.py.ast │ ├── decl_global_forward.py.ast.typed │ ├── decl_nonlocal_forward.py │ ├── decl_nonlocal_forward.py.ast │ ├── decl_nonlocal_forward.py.ast.typed │ ├── error_div_zero.py │ ├── error_div_zero.py.ast.typed │ ├── error_invalid_print.py │ ├── error_invalid_print.py.ast.typed │ ├── error_mod_zero.py │ ├── error_mod_zero.py.ast.typed │ ├── example_classes.py │ ├── example_classes.py.ast │ ├── example_classes.py.ast.typed │ ├── example_contains.py │ ├── example_contains.py.ast │ ├── example_contains.py.ast.typed │ ├── example_counter.py │ ├── example_counter.py.ast │ ├── example_counter.py.ast.typed │ ├── example_exp.py │ ├── example_exp.py.ast │ ├── example_exp.py.ast.typed │ ├── example_linked_list.py │ ├── example_linked_list.py.ast │ ├── example_linked_list.py.ast.typed │ ├── example_rat.py │ ├── example_rat.py.ast │ ├── example_rat.py.ast.typed │ ├── example_sieve.py │ ├── example_sieve.py.ast.typed │ ├── example_tree.py │ ├── example_tree.py.ast.typed │ ├── exp.py │ ├── exp.py.ast.typed │ ├── expr_binary.py │ ├── expr_binary.py.ast │ ├── expr_binary.py.ast.typed │ ├── expr_concat.py │ ├── expr_concat.py.ast │ ├── expr_concat.py.ast.typed │ ├── expr_id.py │ ├── expr_id.py.ast │ ├── expr_id.py.ast.typed │ ├── expr_if.py │ ├── expr_if.py.ast │ ├── expr_if.py.ast.typed │ ├── expr_int.py │ ├── expr_int.py.ast │ ├── expr_int.py.ast.typed │ ├── expr_list_index.py │ ├── expr_list_index.py.ast │ ├── expr_list_index.py.ast.typed │ ├── expr_lists.py │ ├── expr_lists.py.ast │ ├── expr_lists.py.ast.typed │ ├── expr_unary.py │ ├── expr_unary.py.ast │ ├── expr_unary.py.ast.typed │ ├── expr_var_assign.py │ ├── expr_var_assign.py.ast │ ├── expr_var_assign.py.ast.typed │ ├── func_def_call.py │ ├── func_def_call.py.ast │ ├── func_def_call.py.ast.typed │ ├── id_global.py │ ├── id_global.py.ast.typed │ ├── id_local.py │ ├── id_local.py.ast.typed │ ├── len_invalid_1.py │ ├── len_invalid_1.py.ast.typed │ ├── len_invalid_2.py │ ├── len_invalid_2.py.ast.typed │ ├── list_concat.py │ ├── list_concat.py.ast.typed │ ├── list_concat_2.py │ ├── list_concat_2.py.ast.typed │ ├── list_concat_none.py │ ├── list_concat_none.py.ast.typed │ ├── list_get_element.py │ ├── list_get_element.py.ast.typed │ ├── list_get_element_complex.py │ ├── list_get_element_complex.py.ast.typed │ ├── list_get_element_none.py │ ├── list_get_element_none.py.ast.typed │ ├── list_get_element_oob_1.py │ ├── list_get_element_oob_1.py.ast.typed │ ├── list_get_element_oob_2.py │ ├── list_get_element_oob_2.py.ast.typed │ ├── list_get_element_oob_3.py │ ├── list_get_element_oob_3.py.ast.typed │ ├── list_len.py │ ├── list_len.py.ast.typed │ ├── list_len_empty.py │ ├── list_len_empty.py.ast.typed │ ├── list_set_element.py │ ├── list_set_element.py.ast.typed │ ├── list_set_element_none.py │ ├── list_set_element_none.py.ast.typed │ ├── list_set_element_oob_1.py │ ├── list_set_element_oob_1.py.ast.typed │ ├── list_set_element_oob_2.py │ ├── list_set_element_oob_2.py.ast.typed │ ├── list_set_element_oob_3.py │ ├── list_set_element_oob_3.py.ast.typed │ ├── literal_bool.py │ ├── literal_bool.py.ast.typed │ ├── literal_int.py │ ├── literal_int.py.ast.typed │ ├── literal_str.py │ ├── literal_str.py.ast.typed │ ├── nested.py │ ├── nested.py.ast.typed │ ├── nested2.py │ ├── nested2.py.ast.typed │ ├── object_attr_get.py │ ├── object_attr_get.py.ast.typed │ ├── object_attr_get_none.py │ ├── object_attr_get_none.py.ast.typed │ ├── object_attr_set.py │ ├── object_attr_set.py.ast.typed │ ├── object_attr_set_eval_order.py │ ├── object_attr_set_eval_order.py.ast.typed │ ├── object_attr_set_none.py │ ├── object_attr_set_none.py.ast.typed │ ├── object_init.py │ ├── object_init.py.ast.typed │ ├── object_method.py │ ├── object_method.py.ast.typed │ ├── object_method_complex_call.py │ ├── object_method_complex_call.py.ast.typed │ ├── object_method_nested.py │ ├── object_method_nested.py.ast.typed │ ├── object_method_none.py │ ├── object_method_none.py.ast.typed │ ├── object_method_override.py │ ├── object_method_override.py.ast.typed │ ├── op_add.py │ ├── op_add.py.ast.typed │ ├── op_cmp_bool.py │ ├── op_cmp_bool.py.ast.typed │ ├── op_cmp_int.py │ ├── op_cmp_int.py.ast.typed │ ├── op_div_mod.py │ ├── op_div_mod.py.ast.typed │ ├── op_is.py │ ├── op_is.py.ast.typed │ ├── op_logical.py │ ├── op_logical.py.ast.typed │ ├── op_mul.py │ ├── op_mul.py.ast.typed │ ├── op_negate.py │ ├── op_negate.py.ast.typed │ ├── op_sub.py │ ├── op_sub.py.ast.typed │ ├── pass.py │ ├── pass.py.ast.typed │ ├── predef_constructors.py │ ├── predef_constructors.py.ast.typed │ ├── prime.py │ ├── prime.py.ast.typed │ ├── stdlib.py │ ├── stdlib.py.ast.typed │ ├── stmt_for_list.py │ ├── stmt_for_list.py.ast.typed │ ├── stmt_for_list_empty.py │ ├── stmt_for_list_empty.py.ast.typed │ ├── stmt_for_list_eval.py │ ├── stmt_for_list_eval.py.ast.typed │ ├── stmt_for_list_modify.py │ ├── stmt_for_list_modify.py.ast.typed │ ├── stmt_for_list_nested.py │ ├── stmt_for_list_nested.py.ast.typed │ ├── stmt_for_list_nested_same_var.py │ ├── stmt_for_list_nested_same_var.py.ast.typed │ ├── stmt_for_list_none.py │ ├── stmt_for_list_none.py.ast.typed │ ├── stmt_for_list_nonlocal.py │ ├── stmt_for_list_nonlocal.py.ast.typed │ ├── stmt_for_list_return.py │ ├── stmt_for_list_return.py.ast.typed │ ├── stmt_for_lists.py │ ├── stmt_for_lists.py.ast │ ├── stmt_for_lists.py.ast.typed │ ├── stmt_for_str.py │ ├── stmt_for_str.py.ast.typed │ ├── stmt_for_str_empty.py │ ├── stmt_for_str_empty.py.ast.typed │ ├── stmt_for_str_eval.py │ ├── stmt_for_str_eval.py.ast.typed │ ├── stmt_for_str_nested.py │ ├── stmt_for_str_nested.py.ast.typed │ ├── stmt_for_str_same_var.py │ ├── stmt_for_str_same_var.py.ast.typed │ ├── stmt_for_strings.py │ ├── stmt_for_strings.py.ast │ ├── stmt_for_strings.py.ast.typed │ ├── stmt_if.py │ ├── stmt_if.py.ast │ ├── stmt_if.py.ast.typed │ ├── stmt_list_assign.py │ ├── stmt_list_assign.py.ast │ ├── stmt_list_assign.py.ast.typed │ ├── stmt_return_early.py │ ├── stmt_return_early.py.ast.typed │ ├── stmt_var_assign.py │ ├── stmt_var_assign.py.ast │ ├── stmt_var_assign.py.ast.typed │ ├── stmt_while.py │ ├── stmt_while.py.ast │ ├── stmt_while.py.ast.typed │ ├── str_cat.py │ ├── str_cat.py.ast.typed │ ├── str_cat_2.py │ ├── str_cat_2.py.ast.typed │ ├── str_cmp.py │ ├── str_cmp.py.ast.typed │ ├── str_get_element.py │ ├── str_get_element.py.ast.typed │ ├── str_get_element_oob_1.py │ ├── str_get_element_oob_1.py.ast.typed │ ├── str_get_element_oob_2.py │ ├── str_get_element_oob_2.py.ast.typed │ ├── str_get_element_oob_3.py │ ├── str_get_element_oob_3.py.ast.typed │ ├── str_len.py │ ├── str_len.py.ast.typed │ ├── strings.py │ ├── strings.py.ast │ ├── strings.py.ast.typed │ ├── var_assign.py │ └── var_assign.py.ast.typed └── wasm.js /.gitattributes: -------------------------------------------------------------------------------- 1 | test/* linguist-generated -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Danny Yang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | clean: 2 | rm -f *.j 3 | rm -f *.class 4 | rm -f *.cil 5 | rm -f *.exe 6 | rm -f *.ast 7 | rm -f *.ast.typed 8 | rm -f *.test.py 9 | rm -f *.out.py 10 | rm -f *.wasm 11 | rm -f *.wat 12 | rm -f *.ll 13 | rm -f *.s 14 | -------------------------------------------------------------------------------- /compiler/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /compiler/astnodes/__init__.py: -------------------------------------------------------------------------------- 1 | from .assignstmt import AssignStmt 2 | from .declaration import Declaration 3 | from .identifier import Identifier 4 | from .literal import Literal 5 | from .returnstmt import ReturnStmt 6 | from .whilestmt import WhileStmt 7 | from .binaryexpr import BinaryExpr 8 | from .errors import Errors 9 | from .ifexpr import IfExpr 10 | from .memberexpr import MemberExpr 11 | from .stmt import Stmt 12 | from .booleanliteral import BooleanLiteral 13 | from .expr import Expr 14 | from .ifstmt import IfStmt 15 | from .methodcallexpr import MethodCallExpr 16 | from .stringliteral import StringLiteral 17 | from .callexpr import CallExpr 18 | from .exprstmt import ExprStmt 19 | from .indexexpr import IndexExpr 20 | from .node import Node 21 | from .typeannotation import TypeAnnotation 22 | from .classdef import ClassDef 23 | from .forstmt import ForStmt 24 | from .integerliteral import IntegerLiteral 25 | from .nonlocaldecl import NonLocalDecl 26 | from .typedvar import TypedVar 27 | from .classtype import ClassType 28 | from .funcdef import FuncDef 29 | from .listexpr import ListExpr 30 | from .noneliteral import NoneLiteral 31 | from .unaryexpr import UnaryExpr 32 | from .compilererror import CompilerError 33 | from .globaldecl import GlobalDecl 34 | from .listtype import ListType 35 | from .program import Program 36 | from .vardef import VarDef 37 | -------------------------------------------------------------------------------- /compiler/astnodes/assignstmt.py: -------------------------------------------------------------------------------- 1 | from .stmt import Stmt 2 | from .expr import Expr 3 | from typing import List 4 | 5 | 6 | class AssignStmt(Stmt): 7 | 8 | def __init__(self, location: List[int], targets: List[Expr], value: Expr): 9 | super().__init__(location, "AssignStmt") 10 | self.targets = targets 11 | self.value = value 12 | 13 | def preorder(self, visitor): 14 | visitor.AssignStmt(self) 15 | for t in self.targets: 16 | visitor.visit(t) 17 | visitor.visit(self.value) 18 | return self 19 | 20 | def postorder(self, visitor): 21 | for t in self.targets: 22 | visitor.visit(t) 23 | visitor.visit(self.value) 24 | return visitor.AssignStmt(self) 25 | 26 | def visit(self, visitor): 27 | return visitor.AssignStmt(self) 28 | 29 | def toJSON(self, dump_location=True): 30 | d = super().toJSON(dump_location) 31 | d["targets"] = [t.toJSON(dump_location) for t in self.targets] 32 | d["value"] = self.value.toJSON(dump_location) 33 | return d 34 | -------------------------------------------------------------------------------- /compiler/astnodes/binaryexpr.py: -------------------------------------------------------------------------------- 1 | from .expr import Expr 2 | from typing import List 3 | 4 | 5 | class BinaryExpr(Expr): 6 | 7 | def __init__(self, location: List[int], left: Expr, operator: str, right: Expr): 8 | super().__init__(location, "BinaryExpr") 9 | self.left = left 10 | self.right = right 11 | self.operator = operator 12 | 13 | def preorder(self, visitor): 14 | visitor.BinaryExpr(self) 15 | visitor.visit(self.left) 16 | visitor.visit(self.right) 17 | return self 18 | 19 | def postorder(self, visitor): 20 | visitor.visit(self.left) 21 | visitor.visit(self.right) 22 | return visitor.BinaryExpr(self) 23 | 24 | def visit(self, visitor): 25 | return visitor.BinaryExpr(self) 26 | 27 | def toJSON(self, dump_location=True): 28 | d = super().toJSON(dump_location) 29 | d["left"] = self.left.toJSON(dump_location) 30 | d["right"] = self.right.toJSON(dump_location) 31 | d["operator"] = self.operator 32 | return d 33 | -------------------------------------------------------------------------------- /compiler/astnodes/booleanliteral.py: -------------------------------------------------------------------------------- 1 | from .literal import Literal 2 | from typing import List 3 | 4 | 5 | class BooleanLiteral(Literal): 6 | 7 | def __init__(self, location: List[int], value: bool): 8 | super().__init__(location, "BooleanLiteral") 9 | self.value = value 10 | 11 | def visit(self, visitor): 12 | return visitor.BooleanLiteral(self) 13 | -------------------------------------------------------------------------------- /compiler/astnodes/callexpr.py: -------------------------------------------------------------------------------- 1 | from .expr import Expr 2 | from .identifier import Identifier 3 | from typing import List 4 | 5 | 6 | class CallExpr(Expr): 7 | 8 | def __init__(self, location: List[int], function: Identifier, args: List[Expr]): 9 | super().__init__(location, "CallExpr") 10 | self.function = function 11 | self.args = args 12 | self.isConstructor = False 13 | self.freevars = [] # captured free vars 14 | 15 | def postorder(self, visitor): 16 | for a in self.args: 17 | visitor.visit(a) 18 | return visitor.CallExpr(self) 19 | 20 | def preorder(self, visitor): 21 | visitor.CallExpr(self) 22 | for a in self.args: 23 | visitor.visit(a) 24 | return self 25 | 26 | def visit(self, visitor): 27 | return visitor.CallExpr(self) 28 | 29 | def toJSON(self, dump_location=True): 30 | d = super().toJSON(dump_location) 31 | d["function"] = self.function.toJSON(dump_location) 32 | d["args"] = [a.toJSON(dump_location) for a in self.args] 33 | return d 34 | -------------------------------------------------------------------------------- /compiler/astnodes/classtype.py: -------------------------------------------------------------------------------- 1 | from .typeannotation import TypeAnnotation 2 | from typing import List 3 | 4 | 5 | class ClassType(TypeAnnotation): 6 | 7 | def __init__(self, location: List[int], className: str): 8 | super().__init__(location, "ClassType") 9 | self.className = className 10 | 11 | def visit(self, visitor): 12 | return visitor.ClassType(self) 13 | 14 | def toJSON(self, dump_location=True): 15 | d = super().toJSON(dump_location) 16 | d["className"] = self.className 17 | return d 18 | -------------------------------------------------------------------------------- /compiler/astnodes/compilererror.py: -------------------------------------------------------------------------------- 1 | from .node import Node 2 | from typing import List 3 | 4 | 5 | class CompilerError(Node): 6 | 7 | def __init__(self, location: List[int], message: str, syntax: bool = False): 8 | super().__init__(location, "CompilerError") 9 | self.message = message 10 | self.syntax = syntax 11 | 12 | def toJSON(self, dump_location=True): 13 | d = super().toJSON(dump_location) 14 | d["message"] = self.message 15 | return d 16 | -------------------------------------------------------------------------------- /compiler/astnodes/declaration.py: -------------------------------------------------------------------------------- 1 | from .identifier import Identifier 2 | from .node import Node 3 | from typing import List 4 | 5 | 6 | class Declaration(Node): 7 | 8 | def __init__(self, location: List[int], kind: str): 9 | super().__init__(location, kind) 10 | 11 | def getIdentifier(self) -> Identifier: 12 | raise Exception("unimplemented") 13 | -------------------------------------------------------------------------------- /compiler/astnodes/errors.py: -------------------------------------------------------------------------------- 1 | from .node import Node 2 | from .compilererror import CompilerError 3 | from typing import List 4 | 5 | 6 | class Errors(Node): 7 | 8 | def __init__(self, location: List[int], errors: List[CompilerError]): 9 | super().__init__(location, "Errors") 10 | self.errors = errors 11 | 12 | def visit(self, visitor): 13 | return self 14 | 15 | def toJSON(self, dump_location=True): 16 | d = super().toJSON(dump_location) 17 | d["errors"] = [e.toJSON(dump_location) for e in self.errors] 18 | return d 19 | -------------------------------------------------------------------------------- /compiler/astnodes/expr.py: -------------------------------------------------------------------------------- 1 | from .node import Node 2 | from typing import List, Optional, Union 3 | from ..types import ValueType, FuncType 4 | 5 | 6 | class Expr(Node): 7 | inferredType: Optional[Union[ValueType, FuncType]] 8 | 9 | def __init__(self, location: List[int], kind: str): 10 | super().__init__(location, kind) 11 | self.inferredType = None 12 | self.shouldBoxAsRef = False 13 | 14 | def toJSON(self, dump_location=True): 15 | d = super().toJSON(dump_location) 16 | if self.inferredType is not None: 17 | d['inferredType'] = self.inferredType.toJSON(dump_location) 18 | return d 19 | 20 | def inferredValueType(self) -> ValueType: 21 | assert self.inferredType is not None and isinstance( 22 | self.inferredType, ValueType) 23 | return self.inferredType 24 | -------------------------------------------------------------------------------- /compiler/astnodes/exprstmt.py: -------------------------------------------------------------------------------- 1 | from .stmt import Stmt 2 | from .expr import Expr 3 | from typing import List 4 | 5 | 6 | class ExprStmt(Stmt): 7 | 8 | def __init__(self, location: List[int], expr: Expr): 9 | super().__init__(location, "ExprStmt") 10 | self.expr = expr 11 | 12 | def preorder(self, visitor): 13 | visitor.ExprStmt(self) 14 | visitor.visit(self.expr) 15 | return self 16 | 17 | def postorder(self, visitor): 18 | visitor.visit(self.expr) 19 | return visitor.ExprStmt(self) 20 | 21 | def visit(self, visitor): 22 | return visitor.ExprStmt(self) 23 | 24 | def toJSON(self, dump_location=True): 25 | d = super().toJSON(dump_location) 26 | d["expr"] = self.expr.toJSON(dump_location) 27 | return d 28 | -------------------------------------------------------------------------------- /compiler/astnodes/forstmt.py: -------------------------------------------------------------------------------- 1 | from .stmt import Stmt 2 | from .expr import Expr 3 | from .identifier import Identifier 4 | from typing import List 5 | 6 | 7 | class ForStmt(Stmt): 8 | 9 | def __init__(self, location: List[int], identifier: Identifier, iterable: Expr, body: List[Stmt]): 10 | super().__init__(location, "ForStmt") 11 | self.identifier = identifier 12 | self.iterable = iterable 13 | self.body = [s for s in body if s is not None] 14 | 15 | def postorder(self, visitor): 16 | visitor.visit(self.identifier) 17 | visitor.visit(self.iterable) 18 | for s in self.body: 19 | visitor.visit(s) 20 | return visitor.ForStmt(self) 21 | 22 | def preorder(self, visitor): 23 | visitor.ForStmt(self) 24 | visitor.visit(self.identifier) 25 | visitor.visit(self.iterable) 26 | for s in self.body: 27 | visitor.visit(s) 28 | return self 29 | 30 | def visit(self, visitor): 31 | return visitor.ForStmt(self) 32 | 33 | def toJSON(self, dump_location=True): 34 | d = super().toJSON(dump_location) 35 | d["identifier"] = self.identifier.toJSON(dump_location) 36 | d["iterable"] = self.iterable.toJSON(dump_location) 37 | d["body"] = [s.toJSON(dump_location) for s in self.body] 38 | return d 39 | -------------------------------------------------------------------------------- /compiler/astnodes/globaldecl.py: -------------------------------------------------------------------------------- 1 | from .declaration import Declaration 2 | from .identifier import Identifier 3 | from typing import List 4 | 5 | 6 | class GlobalDecl(Declaration): 7 | 8 | def __init__(self, location: List[int], variable: Identifier): 9 | super().__init__(location, "GlobalDecl") 10 | self.variable = variable 11 | 12 | def visit(self, visitor): 13 | return visitor.GlobalDecl(self) 14 | 15 | def toJSON(self, dump_location=True): 16 | d = super().toJSON(dump_location) 17 | d["variable"] = self.variable.toJSON(dump_location) 18 | return d 19 | 20 | def getIdentifier(self): 21 | return self.variable 22 | -------------------------------------------------------------------------------- /compiler/astnodes/ifexpr.py: -------------------------------------------------------------------------------- 1 | from .expr import Expr 2 | from typing import List 3 | 4 | 5 | class IfExpr(Expr): 6 | 7 | def __init__(self, location: List[int], condition: Expr, thenExpr: Expr, elseExpr: Expr): 8 | super().__init__(location, "IfExpr") 9 | self.condition = condition 10 | self.thenExpr = thenExpr 11 | self.elseExpr = elseExpr 12 | 13 | def postorder(self, visitor): 14 | visitor.visit(self.condition) 15 | visitor.visit(self.thenExpr) 16 | visitor.visit(self.elseExpr) 17 | return visitor.IfExpr(self) 18 | 19 | def preorder(self, visitor): 20 | visitor.IfExpr(self) 21 | visitor.visit(self.condition) 22 | visitor.visit(self.thenExpr) 23 | visitor.visit(self.elseExpr) 24 | return self 25 | 26 | def visit(self, visitor): 27 | return visitor.IfExpr(self) 28 | 29 | def toJSON(self, dump_location=True): 30 | d = super().toJSON(dump_location) 31 | d["condition"] = self.condition.toJSON(dump_location) 32 | d["thenExpr"] = self.thenExpr.toJSON(dump_location) 33 | d["elseExpr"] = self.elseExpr.toJSON(dump_location) 34 | return d 35 | -------------------------------------------------------------------------------- /compiler/astnodes/ifstmt.py: -------------------------------------------------------------------------------- 1 | from .stmt import Stmt 2 | from .expr import Expr 3 | from typing import List 4 | 5 | 6 | class IfStmt(Stmt): 7 | 8 | def __init__(self, location: List[int], condition: Expr, thenBody: List[Stmt], elseBody: List[Stmt]): 9 | super().__init__(location, "IfStmt") 10 | self.condition = condition 11 | self.thenBody = [s for s in thenBody if s is not None] 12 | self.elseBody = [s for s in elseBody if s is not None] 13 | 14 | def postorder(self, visitor): 15 | visitor.visit(self.condition) 16 | for s in self.thenBody: 17 | visitor.visit(s) 18 | for s in self.elseBody: 19 | visitor.visit(s) 20 | return visitor.IfStmt(self) 21 | 22 | def preorder(self, visitor): 23 | visitor.IfStmt(self) 24 | visitor.visit(self.condition) 25 | for s in self.thenBody: 26 | visitor.visit(s) 27 | for s in self.elseBody: 28 | visitor.visit(s) 29 | return self 30 | 31 | def visit(self, visitor): 32 | return visitor.IfStmt(self) 33 | 34 | def toJSON(self, dump_location=True): 35 | d = super().toJSON(dump_location) 36 | d["condition"] = self.condition.toJSON(dump_location) 37 | d["thenBody"] = [s.toJSON(dump_location) for s in self.thenBody] 38 | d["elseBody"] = [s.toJSON(dump_location) for s in self.elseBody] 39 | return d 40 | -------------------------------------------------------------------------------- /compiler/astnodes/indexexpr.py: -------------------------------------------------------------------------------- 1 | from .expr import Expr 2 | from typing import List 3 | 4 | 5 | class IndexExpr(Expr): 6 | 7 | def __init__(self, location: List[int], lst: Expr, index: Expr): 8 | super().__init__(location, "IndexExpr") 9 | self.list = lst 10 | self.index = index 11 | 12 | def postorder(self, visitor): 13 | visitor.visit(self.list) 14 | visitor.visit(self.index) 15 | return visitor.IndexExpr(self) 16 | 17 | def preorder(self, visitor): 18 | visitor.IndexExpr(self) 19 | visitor.visit(self.list) 20 | visitor.visit(self.index) 21 | return self 22 | 23 | def visit(self, visitor): 24 | return visitor.IndexExpr(self) 25 | 26 | def toJSON(self, dump_location=True): 27 | d = super().toJSON(dump_location) 28 | d["list"] = self.list.toJSON(dump_location) 29 | d["index"] = self.index.toJSON(dump_location) 30 | return d 31 | -------------------------------------------------------------------------------- /compiler/astnodes/integerliteral.py: -------------------------------------------------------------------------------- 1 | from .literal import Literal 2 | from typing import List 3 | 4 | 5 | class IntegerLiteral(Literal): 6 | 7 | def __init__(self, location: List[int], value: int): 8 | super().__init__(location, "IntegerLiteral") 9 | self.value = value 10 | 11 | def visit(self, visitor): 12 | return visitor.IntegerLiteral(self) 13 | -------------------------------------------------------------------------------- /compiler/astnodes/listexpr.py: -------------------------------------------------------------------------------- 1 | from .expr import Expr 2 | from ..types import ValueType 3 | from typing import List, Optional 4 | 5 | 6 | class ListExpr(Expr): 7 | emptyListType: Optional[ValueType] 8 | 9 | def __init__(self, location: List[int], elements: List[Expr]): 10 | super().__init__(location, "ListExpr") 11 | self.elements = elements 12 | # this is populated by the EmptyListTyper pass 13 | self.emptyListType = None 14 | 15 | def preorder(self, visitor): 16 | visitor.ListExpr(self) 17 | for e in self.elements: 18 | visitor.visit(e) 19 | return self 20 | 21 | def postorder(self, visitor): 22 | for e in self.elements: 23 | visitor.visit(e) 24 | return visitor.ListExpr(self) 25 | 26 | def visit(self, visitor): 27 | return visitor.ListExpr(self) 28 | 29 | def toJSON(self, dump_location=True): 30 | d = super().toJSON(dump_location) 31 | d["elements"] = [e.toJSON(dump_location) for e in self.elements] 32 | return d 33 | -------------------------------------------------------------------------------- /compiler/astnodes/listtype.py: -------------------------------------------------------------------------------- 1 | from .typeannotation import TypeAnnotation 2 | from typing import List 3 | 4 | 5 | class ListType(TypeAnnotation): 6 | 7 | def __init__(self, location: List[int], elementType: TypeAnnotation): 8 | super().__init__(location, "ListType") 9 | self.elementType = elementType 10 | 11 | def visit(self, visitor): 12 | return visitor.ListType(self) 13 | 14 | def toJSON(self, dump_location=True): 15 | d = super().toJSON(dump_location) 16 | d["elementType"] = self.elementType.toJSON(dump_location) 17 | return d 18 | -------------------------------------------------------------------------------- /compiler/astnodes/literal.py: -------------------------------------------------------------------------------- 1 | from .expr import Expr 2 | from typing import List 3 | 4 | 5 | class Literal(Expr): 6 | 7 | def __init__(self, location: List[int], kind: str): 8 | super().__init__(location, kind) 9 | self.value = None 10 | 11 | def toJSON(self, dump_location=True): 12 | d = super().toJSON(dump_location) 13 | if self.value is not None: 14 | d['value'] = self.value 15 | return d 16 | -------------------------------------------------------------------------------- /compiler/astnodes/memberexpr.py: -------------------------------------------------------------------------------- 1 | from .expr import Expr 2 | from .identifier import Identifier 3 | from typing import List, Union 4 | from ..types import FuncType, ValueType 5 | 6 | 7 | class MemberExpr(Expr): 8 | 9 | def __init__(self, location: List[int], obj: Expr, member: Identifier): 10 | super().__init__(location, "MemberExpr") 11 | self.object = obj 12 | self.member = member 13 | 14 | def preorder(self, visitor): 15 | visitor.MemberExpr(self) 16 | visitor.visit(self.object) 17 | return self 18 | 19 | def postorder(self, visitor): 20 | visitor.visit(self.object) 21 | return visitor.MemberExpr(self) 22 | 23 | def visit(self, visitor): 24 | return visitor.MemberExpr(self) 25 | 26 | def toJSON(self, dump_location=True): 27 | d = super().toJSON(dump_location) 28 | d["object"] = self.object.toJSON(dump_location) 29 | d["member"] = self.member.toJSON(dump_location) 30 | return d 31 | -------------------------------------------------------------------------------- /compiler/astnodes/methodcallexpr.py: -------------------------------------------------------------------------------- 1 | from .expr import Expr 2 | from .memberexpr import MemberExpr 3 | from typing import List 4 | 5 | 6 | class MethodCallExpr(Expr): 7 | 8 | def __init__(self, location: List[int], method: MemberExpr, args: List[Expr]): 9 | super().__init__(location, "MethodCallExpr") 10 | self.method = method 11 | self.args = args 12 | 13 | def preorder(self, visitor): 14 | visitor.MethodCallExpr(self) 15 | visitor.visit(self.method.object) 16 | for a in self.args: 17 | visitor.visit(a) 18 | return self 19 | 20 | def postorder(self, visitor): 21 | visitor.visit(self.method.object) 22 | for a in self.args: 23 | visitor.visit(a) 24 | return visitor.MethodCallExpr(self) 25 | 26 | def visit(self, visitor): 27 | return visitor.MethodCallExpr(self) 28 | 29 | def toJSON(self, dump_location=True): 30 | d = super().toJSON(dump_location) 31 | d["method"] = self.method.toJSON(dump_location) 32 | d["args"] = [a.toJSON(dump_location) for a in self.args] 33 | return d 34 | -------------------------------------------------------------------------------- /compiler/astnodes/node.py: -------------------------------------------------------------------------------- 1 | from typing import List, Self, Optional 2 | 3 | 4 | class Node: 5 | errorMsg: Optional[str] 6 | 7 | def __init__(self, location: List[int], kind: str): 8 | if len(location) != 2: 9 | raise Exception('location must be length 2') 10 | self.kind = kind 11 | self.location = location 12 | self.errorMsg = None 13 | 14 | def visit(self, visitor) -> Self: 15 | raise Exception('operation not supported') 16 | 17 | def preorder(self, visitor) -> Self: 18 | return self.visit(visitor) 19 | 20 | def postorder(self, visitor) -> Self: 21 | return self.visit(visitor) 22 | 23 | def toJSON(self, dump_location=True) -> dict: 24 | d = {} 25 | d['kind'] = self.kind 26 | if dump_location: 27 | d['location'] = self.location + self.location 28 | if self.errorMsg is not None: 29 | d['errorMsg'] = self.errorMsg 30 | return d 31 | -------------------------------------------------------------------------------- /compiler/astnodes/noneliteral.py: -------------------------------------------------------------------------------- 1 | from .literal import Literal 2 | from typing import List 3 | 4 | 5 | class NoneLiteral(Literal): 6 | 7 | def __init__(self, location: List[int]): 8 | super().__init__(location, "NoneLiteral") 9 | self.value = None 10 | 11 | def visit(self, visitor): 12 | return visitor.NoneLiteral(self) 13 | -------------------------------------------------------------------------------- /compiler/astnodes/nonlocaldecl.py: -------------------------------------------------------------------------------- 1 | from .declaration import Declaration 2 | from .identifier import Identifier 3 | from typing import List 4 | 5 | 6 | class NonLocalDecl(Declaration): 7 | 8 | def __init__(self, location: List[int], variable: Identifier): 9 | super().__init__(location, "NonLocalDecl") 10 | self.variable = variable 11 | 12 | def visit(self, visitor): 13 | return visitor.NonLocalDecl(self) 14 | 15 | def toJSON(self, dump_location=True): 16 | d = super().toJSON(dump_location) 17 | d["variable"] = self.variable.toJSON(dump_location) 18 | return d 19 | 20 | def getIdentifier(self): 21 | return self.variable 22 | -------------------------------------------------------------------------------- /compiler/astnodes/program.py: -------------------------------------------------------------------------------- 1 | from .node import Node 2 | from .declaration import Declaration 3 | from .stmt import Stmt 4 | from .errors import Errors 5 | from typing import List 6 | 7 | # root AST for source file 8 | 9 | 10 | class Program(Node): 11 | 12 | def __init__(self, location: List[int], declarations: List[Declaration], statements: List[Stmt], errors: Errors): 13 | super().__init__(location, "Program") 14 | self.declarations = [d for d in declarations if d is not None] 15 | self.statements = [s for s in statements if s is not None] 16 | self.errors = errors 17 | 18 | def preorder(self, visitor): 19 | visitor.Program(self) 20 | for d in self.declarations: 21 | visitor.visit(d) 22 | for s in self.statements: 23 | visitor.visit(s) 24 | return self 25 | 26 | def postorder(self, visitor): 27 | for d in self.declarations: 28 | visitor.visit(d) 29 | for s in self.statements: 30 | visitor.visit(s) 31 | return visitor.Program(self) 32 | 33 | def visit(self, visitor): 34 | return visitor.Program(self) 35 | 36 | def toJSON(self, dump_location=True): 37 | d = super().toJSON(dump_location) 38 | d['declarations'] = [d.toJSON(dump_location) 39 | for d in self.declarations] 40 | d['statements'] = [s.toJSON(dump_location) for s in self.statements] 41 | d['errors'] = self.errors.toJSON(dump_location) 42 | return d 43 | -------------------------------------------------------------------------------- /compiler/astnodes/returnstmt.py: -------------------------------------------------------------------------------- 1 | from .stmt import Stmt 2 | from .expr import Expr 3 | from ..types import ValueType 4 | from typing import List, Optional 5 | 6 | 7 | class ReturnStmt(Stmt): 8 | expType: Optional[ValueType] 9 | 10 | def __init__(self, location: List[int], value: Optional[Expr]): 11 | super().__init__(location, "ReturnStmt") 12 | self.value = value 13 | self.isReturn = True 14 | self.expType = None 15 | 16 | def postorder(self, visitor): 17 | if self.value is not None: 18 | visitor.visit(self.value) 19 | return visitor.ReturnStmt(self) 20 | 21 | def preorder(self, visitor): 22 | visitor.ReturnStmt(self) 23 | if self.value is not None: 24 | visitor.visit(self.value) 25 | return self 26 | 27 | def visit(self, visitor): 28 | return visitor.ReturnStmt(self) 29 | 30 | def toJSON(self, dump_location=True): 31 | d = super().toJSON(dump_location) 32 | if self.value is not None: 33 | d["value"] = self.value.toJSON(dump_location) 34 | else: 35 | d["value"] = None 36 | return d 37 | -------------------------------------------------------------------------------- /compiler/astnodes/stmt.py: -------------------------------------------------------------------------------- 1 | from .node import Node 2 | from typing import List 3 | 4 | 5 | class Stmt(Node): 6 | 7 | def __init__(self, location: List[int], kind: str): 8 | super().__init__(location, kind) 9 | self.isReturn = False 10 | -------------------------------------------------------------------------------- /compiler/astnodes/stringliteral.py: -------------------------------------------------------------------------------- 1 | from .literal import Literal 2 | from typing import List 3 | 4 | 5 | class StringLiteral(Literal): 6 | 7 | def __init__(self, location: List[int], value: str): 8 | super().__init__(location, "StringLiteral") 9 | self.value = value 10 | 11 | def visit(self, visitor): 12 | return visitor.StringLiteral(self) 13 | -------------------------------------------------------------------------------- /compiler/astnodes/typeannotation.py: -------------------------------------------------------------------------------- 1 | from .node import Node 2 | from typing import List 3 | 4 | 5 | class TypeAnnotation(Node): 6 | 7 | def __init__(self, location: List[int], kind: str): 8 | super().__init__(location, kind) 9 | -------------------------------------------------------------------------------- /compiler/astnodes/typedvar.py: -------------------------------------------------------------------------------- 1 | from .node import Node 2 | from .identifier import Identifier 3 | from .typeannotation import TypeAnnotation 4 | from ..types import ValueType, VarInstance 5 | from typing import List, Optional 6 | 7 | 8 | class TypedVar(Node): 9 | t: Optional[ValueType] = None # the typechecked type goes here 10 | varInstance: Optional[VarInstance] = None 11 | 12 | def __init__(self, location: List[int], identifier: Identifier, typ: TypeAnnotation): 13 | super().__init__(location, "TypedVar") 14 | self.identifier = identifier 15 | self.type = typ 16 | 17 | def name(self): 18 | return self.identifier.name 19 | 20 | def visit(self, visitor): 21 | return visitor.TypedVar(self) 22 | 23 | def toJSON(self, dump_location=True): 24 | d = super().toJSON(dump_location) 25 | d["identifier"] = self.identifier.toJSON(dump_location) 26 | d["type"] = self.type.toJSON(dump_location) 27 | return d 28 | 29 | def varInstanceX(self) -> VarInstance: 30 | assert self.varInstance is not None 31 | return self.varInstance 32 | 33 | def getTypeX(self) -> ValueType: 34 | assert self.t is not None 35 | return self.t 36 | -------------------------------------------------------------------------------- /compiler/astnodes/unaryexpr.py: -------------------------------------------------------------------------------- 1 | from .expr import Expr 2 | from typing import List 3 | 4 | 5 | class UnaryExpr(Expr): 6 | 7 | def __init__(self, location: List[int], operator: str, operand: Expr): 8 | super().__init__(location, "UnaryExpr") 9 | self.operand = operand 10 | self.operator = operator 11 | 12 | def preorder(self, visitor): 13 | visitor.UnaryExpr(self) 14 | visitor.visit(self.operand) 15 | return self 16 | 17 | def postorder(self, visitor): 18 | visitor.visit(self.operand) 19 | return visitor.UnaryExpr(self) 20 | 21 | def visit(self, visitor): 22 | return visitor.UnaryExpr(self) 23 | 24 | def toJSON(self, dump_location=True): 25 | d = super().toJSON(dump_location) 26 | d["operator"] = self.operator 27 | d["operand"] = self.operand.toJSON(dump_location) 28 | return d 29 | -------------------------------------------------------------------------------- /compiler/astnodes/vardef.py: -------------------------------------------------------------------------------- 1 | from .declaration import Declaration 2 | from .expr import Expr 3 | from .identifier import Identifier 4 | from .typedvar import TypedVar 5 | from typing import List, Optional 6 | 7 | 8 | class VarDef(Declaration): 9 | attrOfClass: Optional[str] 10 | 11 | def __init__(self, location: List[int], var: TypedVar, value: Expr, isAttr: bool = False, attrOfClass=None): 12 | super().__init__(location, "VarDef") 13 | self.var = var 14 | self.value = value 15 | self.isAttr = isAttr 16 | self.attrOfClass = attrOfClass 17 | 18 | def preorder(self, visitor): 19 | visitor.VarDef(self) 20 | visitor.visit(self.value) 21 | return self 22 | 23 | def postorder(self, visitor): 24 | visitor.visit(self.value) 25 | return visitor.VarDef(self) 26 | 27 | def visit(self, visitor): 28 | return visitor.VarDef(self) 29 | 30 | def toJSON(self, dump_location=True): 31 | d = super().toJSON(dump_location) 32 | d["var"] = self.var.toJSON(dump_location) 33 | d["value"] = self.value.toJSON(dump_location) 34 | return d 35 | 36 | def getIdentifier(self) -> Identifier: 37 | return self.var.identifier 38 | 39 | def getName(self) -> str: 40 | return self.var.identifier.name 41 | -------------------------------------------------------------------------------- /compiler/astnodes/whilestmt.py: -------------------------------------------------------------------------------- 1 | from .stmt import Stmt 2 | from .expr import Expr 3 | from typing import List 4 | 5 | 6 | class WhileStmt(Stmt): 7 | 8 | def __init__(self, location: List[int], condition: Expr, body: List[Stmt]): 9 | super().__init__(location, "WhileStmt") 10 | self.condition = condition 11 | self.body = [s for s in body if s is not None] 12 | 13 | def postorder(self, visitor): 14 | visitor.visit(self.condition) 15 | for s in self.body: 16 | visitor.visit(s) 17 | return visitor.WhileStmt(self) 18 | 19 | def preorder(self, visitor): 20 | visitor.WhileStmt(self) 21 | visitor.visit(self.condition) 22 | for s in self.body: 23 | visitor.visit(s) 24 | return self 25 | 26 | def visit(self, visitor): 27 | return visitor.WhileStmt(self) 28 | 29 | def toJSON(self, dump_location=True): 30 | d = super().toJSON(dump_location) 31 | d["condition"] = self.condition.toJSON(dump_location) 32 | d["body"] = [s.toJSON(dump_location) for s in self.body] 33 | return d 34 | -------------------------------------------------------------------------------- /compiler/builder.py: -------------------------------------------------------------------------------- 1 | from typing import List, Union, cast 2 | 3 | 4 | class Builder: 5 | def __init__(self, name: str): 6 | self.name = name 7 | self.lines: List[Union[str, Builder]] = [] # list of strings or children builders 8 | self.indentation = 0 9 | 10 | def newLine(self, line=""): 11 | self.lines.append((self.indentation * " ") + line) 12 | return self 13 | 14 | # returns a reference to the child builder 15 | def newBlock(self): 16 | child = Builder(self.name) 17 | child.indentation = self.indentation 18 | self.lines.append(child) 19 | return child 20 | 21 | def addText(self, text=""): 22 | if len(self.lines) == 0 or isinstance(self.lines[-1], Builder): 23 | self.newLine() 24 | self.lines[-1] = cast(str, self.lines[-1]) + text 25 | return self 26 | 27 | def indent(self): 28 | self.indentation += 1 29 | return self 30 | 31 | def unindent(self): 32 | self.indentation -= 1 33 | return self 34 | 35 | def emit(self) -> str: 36 | lines = [] 37 | for l in self.lines: 38 | if isinstance(l, str): 39 | lines.append(l) 40 | else: 41 | lines.append(l.emit()) 42 | return "\n".join(lines) 43 | -------------------------------------------------------------------------------- /compiler/typeeraser.py: -------------------------------------------------------------------------------- 1 | from .astnodes import * 2 | from .types import * 3 | from .visitor import Visitor 4 | 5 | # A utility visitor to erase the inferred types of expressions 6 | 7 | 8 | class TypeEraser(Visitor): 9 | 10 | def visit(self, node: Node): 11 | if isinstance(node, Expr): 12 | node.inferredType = None 13 | return node.postorder(self) 14 | 15 | def Program(self, node: Program): 16 | for d in node.declarations: 17 | self.visit(d) 18 | for s in node.statements: 19 | self.visit(s) 20 | 21 | def ClassDef(self, node: ClassDef): 22 | for d in node.declarations: 23 | self.visit(d) 24 | 25 | def FuncDef(self, node: FuncDef): 26 | for d in node.declarations: 27 | self.visit(d) 28 | for s in node.statements: 29 | self.visit(s) 30 | 31 | def CallExpr(self, node: CallExpr): 32 | self.visit(node.function) 33 | 34 | def MethodCallExpr(self, node: MethodCallExpr): 35 | self.visit(node.method) 36 | 37 | def NonLocalDecl(self, node: NonLocalDecl): 38 | self.visit(node.variable) 39 | 40 | def GlobalDecl(self, node: GlobalDecl): 41 | self.visit(node.variable) 42 | -------------------------------------------------------------------------------- /compiler/types/Types.py: -------------------------------------------------------------------------------- 1 | from .classvaluetype import ClassValueType 2 | 3 | # factories for types 4 | 5 | 6 | def ObjectType(): 7 | return ClassValueType("object") 8 | 9 | 10 | def IntType(): 11 | return ClassValueType("int") 12 | 13 | 14 | def StrType(): 15 | return ClassValueType("str") 16 | 17 | 18 | def BoolType(): 19 | return ClassValueType("bool") 20 | 21 | 22 | def NoneType(): 23 | return ClassValueType("") 24 | 25 | 26 | def EmptyType(): 27 | return ClassValueType("") 28 | -------------------------------------------------------------------------------- /compiler/types/__init__.py: -------------------------------------------------------------------------------- 1 | from .classvaluetype import ClassValueType, SpecialClass 2 | from .functype import FuncType 3 | from .listvaluetype import ListValueType 4 | from .symboltype import SymbolType 5 | from .valuetype import ValueType 6 | from .Types import * 7 | from .varinstance import VarInstance 8 | -------------------------------------------------------------------------------- /compiler/types/listvaluetype.py: -------------------------------------------------------------------------------- 1 | from .valuetype import ValueType 2 | from llvmlite import ir 3 | 4 | 5 | class ListValueType(ValueType): 6 | elementType: ValueType 7 | 8 | def __init__(self, elementType: ValueType): 9 | self.elementType = elementType 10 | 11 | def __eq__(self, other): 12 | if isinstance(other, ListValueType): 13 | return self.elementType == other.elementType 14 | return False 15 | 16 | def getJavaSignature(self, isList=False) -> str: 17 | return "[" + self.elementType.getJavaSignature(True) 18 | 19 | def getJavaName(self, isList=False) -> str: 20 | return "[" + self.elementType.getJavaSignature(True) 21 | 22 | def getCILName(self) -> str: 23 | return self.elementType.getCILName() + "[]" 24 | 25 | def getCILSignature(self) -> str: 26 | return self.getCILName() 27 | 28 | def isListType(self) -> bool: 29 | return True 30 | 31 | def isJavaRef(self) -> bool: 32 | return True 33 | 34 | def __str__(self): 35 | return "[{}]".format(str(self.elementType)) 36 | 37 | def __hash__(self): 38 | return str(self).__hash__() 39 | 40 | def toJSON(self, dump_location=True) -> dict: 41 | return { 42 | "kind": "ListValueType", 43 | "elementType": self.elementType.toJSON(dump_location) 44 | } 45 | 46 | def getWasmName(self) -> str: 47 | return "i32" 48 | 49 | def getLLVMType(self) -> ir.Type: 50 | return ir.IntType(8).as_pointer() 51 | -------------------------------------------------------------------------------- /compiler/types/symboltype.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Self 2 | 3 | 4 | class SymbolType: 5 | # base class for types 6 | 7 | def isValueType(self) -> bool: 8 | return False 9 | 10 | def isListType(self) -> bool: 11 | return False 12 | 13 | def isFuncType(self) -> bool: 14 | return False 15 | 16 | def isSpecialType(self) -> bool: 17 | return False 18 | 19 | def toJSON(self, dump_location=True) -> dict: 20 | raise Exception("unsupported") 21 | -------------------------------------------------------------------------------- /compiler/types/valuetype.py: -------------------------------------------------------------------------------- 1 | from .symboltype import SymbolType 2 | import llvmlite.ir as ir 3 | 4 | 5 | class ValueType(SymbolType): 6 | def isValueType(self) -> bool: 7 | return True 8 | 9 | def isNone(self) -> bool: 10 | return False 11 | 12 | def toJSON(self, dump_location=True) -> dict: 13 | raise Exception("unsupported") 14 | 15 | def getCILName(self) -> str: 16 | raise Exception("unsupported") 17 | 18 | def getCILSignature(self) -> str: 19 | raise Exception("unsupported") 20 | 21 | def getJavaName(self, isList: bool = False) -> str: 22 | raise Exception("unsupported") 23 | 24 | def getJavaSignature(self, isList: bool = False) -> str: 25 | raise Exception("unsupported") 26 | 27 | def isJavaRef(self) -> bool: 28 | raise Exception("unsupported") 29 | 30 | def isListType(self) -> bool: 31 | raise Exception("unsupported") 32 | 33 | def getLLVMType(self) -> ir.Type: 34 | raise Exception("unsupported") 35 | 36 | def getWasmName(self) -> str: 37 | raise Exception("unsupported") 38 | -------------------------------------------------------------------------------- /compiler/types/varinstance.py: -------------------------------------------------------------------------------- 1 | class VarInstance: 2 | isNonlocal = False 3 | isGlobal = False 4 | isSelf = False 5 | -------------------------------------------------------------------------------- /compiler/varcollector.py: -------------------------------------------------------------------------------- 1 | from typing import Sequence, List 2 | from .astnodes import * 3 | from .types import * 4 | from .visitor import Visitor 5 | 6 | 7 | class VarCollector(Visitor): 8 | # simple visitor to collect all the identifiers used as expressions or assignment targets 9 | vars: List[Identifier] 10 | 11 | def __init__(self): 12 | self.vars = [] 13 | 14 | def getVars(self, node: Node): 15 | self.visit(node) 16 | return self.vars 17 | 18 | def getVarsFromList(self, nodes: Sequence[Node]): 19 | for n in nodes: 20 | self.visit(n) 21 | return self.vars 22 | 23 | def visit(self, node: Node): 24 | return node.postorder(self) 25 | 26 | def Identifier(self, node: Identifier): 27 | self.vars.append(node) 28 | -------------------------------------------------------------------------------- /demo_cil.sh: -------------------------------------------------------------------------------- 1 | # utility for compiling a Chocopy file to .exe files and running it 2 | base_name="$(basename $1 .py)" 3 | 4 | rm -f *.cil 5 | rm -f *.exe 6 | python3 main.py --mode cil $1 . 7 | ls *.cil | xargs -L1 ilasm 8 | echo "Running program $base_name..." 9 | mono $base_name.exe -------------------------------------------------------------------------------- /demo_jvm.sh: -------------------------------------------------------------------------------- 1 | # utility for compiling a Chocopy file to .class files and running it 2 | base_name="$(basename $1 .py)" 3 | 4 | rm -f *.j 5 | rm -f *.class 6 | python3 main.py --mode jvm $1 . 7 | ls *.j | xargs -L1 python3 ../Krakatau/assemble.py -q 8 | echo "Running program $base_name..." 9 | java -cp . $base_name -------------------------------------------------------------------------------- /demo_llvm.sh: -------------------------------------------------------------------------------- 1 | # utility for compiling a Chocopy file to LLVM IR and running it 2 | base_name="$(basename $1 .py)" 3 | 4 | rm -f *.ll 5 | rm -f *.s 6 | 7 | python3 main.py --mode llvm $1 . 8 | lli $base_name.ll 9 | 10 | 11 | -------------------------------------------------------------------------------- /demo_wasm.sh: -------------------------------------------------------------------------------- 1 | # utility for compiling a Chocopy file to .wasm files and running it 2 | base_name="$(basename $1 .py)" 3 | 4 | rm -f *.wat 5 | rm -f *.wasm 6 | 7 | python3 main.py --mode wasm $1 . 8 | wat2wasm $base_name.wat -o $base_name.wasm 9 | echo "Running program $base_name..." 10 | node wasm.js $base_name.wasm 11 | 12 | -------------------------------------------------------------------------------- /pyrightconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "compiler" 4 | ], 5 | "reportMissingImports": true, 6 | "reportMissingTypeStubs": false, 7 | "pythonVersion": "3.11" 8 | } -------------------------------------------------------------------------------- /tests/parse/bad_annotation.py: -------------------------------------------------------------------------------- 1 | x:[int, int] = 2 -------------------------------------------------------------------------------- /tests/parse/bad_assign_expr1.py: -------------------------------------------------------------------------------- 1 | x = (y = 2) 2 | -------------------------------------------------------------------------------- /tests/parse/bad_assign_expr2.py: -------------------------------------------------------------------------------- 1 | print(x = 1) 2 | -------------------------------------------------------------------------------- /tests/parse/bad_decl_location.py: -------------------------------------------------------------------------------- 1 | def f(x:int)->int: 2 | if True: 3 | z:int = 2 4 | return x -------------------------------------------------------------------------------- /tests/parse/bad_decl_location2.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | x = 2 3 | y:int = 2 -------------------------------------------------------------------------------- /tests/parse/bad_decl_location3.py: -------------------------------------------------------------------------------- 1 | def f(x:int)->int: 2 | x = 2 3 | z:int = 2 4 | return x -------------------------------------------------------------------------------- /tests/parse/bad_func_def.py: -------------------------------------------------------------------------------- 1 | def foo(a, b) -> 1: 2 | x:int = a 3 | return 1 4 | 5 | print(1) 6 | print(3**6) 7 | -------------------------------------------------------------------------------- /tests/parse/bad_indentation.py: -------------------------------------------------------------------------------- 1 | x = 1 2 | y = 2 3 | z = 3 4 | -------------------------------------------------------------------------------- /tests/parse/bad_inheritance.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | pass 3 | 4 | class B(object): 5 | pass 6 | 7 | class C(A,B): 8 | pass -------------------------------------------------------------------------------- /tests/parse/bad_inner_class.py: -------------------------------------------------------------------------------- 1 | class A: 2 | class B: 3 | pass 4 | pass -------------------------------------------------------------------------------- /tests/parse/bad_inner_class2.py: -------------------------------------------------------------------------------- 1 | def f()->int: 2 | class C: 3 | pass -------------------------------------------------------------------------------- /tests/parse/bad_keywords.py: -------------------------------------------------------------------------------- 1 | x:int = 5 2 | x = f(arg=x) -------------------------------------------------------------------------------- /tests/parse/bad_literal.py: -------------------------------------------------------------------------------- 1 | x:float = 5.55 -------------------------------------------------------------------------------- /tests/parse/bad_missing_annotation.py: -------------------------------------------------------------------------------- 1 | def f(x)->int: 2 | return x -------------------------------------------------------------------------------- /tests/parse/bad_slice.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | y:[int] = None 3 | x = [1,2,3] 4 | y = x[1:2] -------------------------------------------------------------------------------- /tests/parse/bad_stmt.py: -------------------------------------------------------------------------------- 1 | 1 + 2 2 | 3 == 4 or (not False && True) 3 | 5 + 6 4 | 7 << 8 5 | -------------------------------------------------------------------------------- /tests/parse/bad_var_decl.py: -------------------------------------------------------------------------------- 1 | def f()->int: 2 | return 3 3 | 4 | x:int = f() -------------------------------------------------------------------------------- /tests/parse/bad_var_decl2.py: -------------------------------------------------------------------------------- 1 | x:int 2 | -------------------------------------------------------------------------------- /tests/parse/bad_while_else.py: -------------------------------------------------------------------------------- 1 | x:int = 5 2 | while True: 3 | x = 4 4 | else: 5 | x = 3 6 | -------------------------------------------------------------------------------- /tests/parse/chained_mixed_assignments.py: -------------------------------------------------------------------------------- 1 | x[0] = y = z.f = 1 2 | z.g = y = x[0] 3 | -------------------------------------------------------------------------------- /tests/parse/chained_mixed_assignments.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 2, 14 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "AssignStmt", 7 | "location" : [ 1, 1, 1, 18 ], 8 | "targets" : [ { 9 | "kind" : "IndexExpr", 10 | "location" : [ 1, 1, 1, 4 ], 11 | "list" : { 12 | "kind" : "Identifier", 13 | "location" : [ 1, 1, 1, 1 ], 14 | "name" : "x" 15 | }, 16 | "index" : { 17 | "kind" : "IntegerLiteral", 18 | "location" : [ 1, 3, 1, 3 ], 19 | "value" : 0 20 | } 21 | }, { 22 | "kind" : "Identifier", 23 | "location" : [ 1, 8, 1, 8 ], 24 | "name" : "y" 25 | }, { 26 | "kind" : "MemberExpr", 27 | "location" : [ 1, 12, 1, 14 ], 28 | "object" : { 29 | "kind" : "Identifier", 30 | "location" : [ 1, 12, 1, 12 ], 31 | "name" : "z" 32 | }, 33 | "member" : { 34 | "kind" : "Identifier", 35 | "location" : [ 1, 14, 1, 14 ], 36 | "name" : "f" 37 | } 38 | } ], 39 | "value" : { 40 | "kind" : "IntegerLiteral", 41 | "location" : [ 1, 18, 1, 18 ], 42 | "value" : 1 43 | } 44 | }, { 45 | "kind" : "AssignStmt", 46 | "location" : [ 2, 1, 2, 14 ], 47 | "targets" : [ { 48 | "kind" : "MemberExpr", 49 | "location" : [ 2, 1, 2, 3 ], 50 | "object" : { 51 | "kind" : "Identifier", 52 | "location" : [ 2, 1, 2, 1 ], 53 | "name" : "z" 54 | }, 55 | "member" : { 56 | "kind" : "Identifier", 57 | "location" : [ 2, 3, 2, 3 ], 58 | "name" : "g" 59 | } 60 | }, { 61 | "kind" : "Identifier", 62 | "location" : [ 2, 7, 2, 7 ], 63 | "name" : "y" 64 | } ], 65 | "value" : { 66 | "kind" : "IndexExpr", 67 | "location" : [ 2, 11, 2, 14 ], 68 | "list" : { 69 | "kind" : "Identifier", 70 | "location" : [ 2, 11, 2, 11 ], 71 | "name" : "x" 72 | }, 73 | "index" : { 74 | "kind" : "IntegerLiteral", 75 | "location" : [ 2, 13, 2, 13 ], 76 | "value" : 0 77 | } 78 | } 79 | } ], 80 | "errors" : { 81 | "errors" : [ ], 82 | "kind" : "Errors", 83 | "location" : [ 0, 0, 0, 0 ] 84 | } 85 | } -------------------------------------------------------------------------------- /tests/parse/chained_var_assignments.py: -------------------------------------------------------------------------------- 1 | x = y = z = 1 2 | -------------------------------------------------------------------------------- /tests/parse/chained_var_assignments.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 13 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "AssignStmt", 7 | "location" : [ 1, 1, 1, 13 ], 8 | "targets" : [ { 9 | "kind" : "Identifier", 10 | "location" : [ 1, 1, 1, 1 ], 11 | "name" : "x" 12 | }, { 13 | "kind" : "Identifier", 14 | "location" : [ 1, 5, 1, 5 ], 15 | "name" : "y" 16 | }, { 17 | "kind" : "Identifier", 18 | "location" : [ 1, 9, 1, 9 ], 19 | "name" : "z" 20 | } ], 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 13, 1, 13 ], 24 | "value" : 1 25 | } 26 | } ], 27 | "errors" : { 28 | "errors" : [ ], 29 | "kind" : "Errors", 30 | "location" : [ 0, 0, 0, 0 ] 31 | } 32 | } -------------------------------------------------------------------------------- /tests/parse/class_attr.py: -------------------------------------------------------------------------------- 1 | class Foo(object): 2 | x:int = 1 3 | 4 | f = Foo() 5 | -------------------------------------------------------------------------------- /tests/parse/class_attr.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 4, 9 ], 4 | "declarations" : [ { 5 | "kind" : "ClassDef", 6 | "location" : [ 1, 1, 2, 13 ], 7 | "name" : { 8 | "kind" : "Identifier", 9 | "location" : [ 1, 7, 1, 9 ], 10 | "name" : "Foo" 11 | }, 12 | "superClass" : { 13 | "kind" : "Identifier", 14 | "location" : [ 1, 11, 1, 16 ], 15 | "name" : "object" 16 | }, 17 | "declarations" : [ { 18 | "kind" : "VarDef", 19 | "location" : [ 2, 5, 2, 13 ], 20 | "var" : { 21 | "kind" : "TypedVar", 22 | "location" : [ 2, 5, 2, 9 ], 23 | "identifier" : { 24 | "kind" : "Identifier", 25 | "location" : [ 2, 5, 2, 5 ], 26 | "name" : "x" 27 | }, 28 | "type" : { 29 | "kind" : "ClassType", 30 | "location" : [ 2, 7, 2, 9 ], 31 | "className" : "int" 32 | } 33 | }, 34 | "value" : { 35 | "kind" : "IntegerLiteral", 36 | "location" : [ 2, 13, 2, 13 ], 37 | "value" : 1 38 | } 39 | } ] 40 | } ], 41 | "statements" : [ { 42 | "kind" : "AssignStmt", 43 | "location" : [ 4, 1, 4, 9 ], 44 | "targets" : [ { 45 | "kind" : "Identifier", 46 | "location" : [ 4, 1, 4, 1 ], 47 | "name" : "f" 48 | } ], 49 | "value" : { 50 | "kind" : "CallExpr", 51 | "location" : [ 4, 5, 4, 9 ], 52 | "function" : { 53 | "kind" : "Identifier", 54 | "location" : [ 4, 5, 4, 7 ], 55 | "name" : "Foo" 56 | }, 57 | "args" : [ ] 58 | } 59 | } ], 60 | "errors" : { 61 | "errors" : [ ], 62 | "kind" : "Errors", 63 | "location" : [ 0, 0, 0, 0 ] 64 | } 65 | } -------------------------------------------------------------------------------- /tests/parse/class_attr_get.py: -------------------------------------------------------------------------------- 1 | class Foo(object): 2 | x:int = 1 3 | 4 | f = Foo() 5 | print(f.x) 6 | -------------------------------------------------------------------------------- /tests/parse/class_attr_set.py: -------------------------------------------------------------------------------- 1 | class Foo(object): 2 | x:int = 1 3 | 4 | f = Foo() 5 | f.x = 2 6 | -------------------------------------------------------------------------------- /tests/parse/class_constructor.py: -------------------------------------------------------------------------------- 1 | class Foo(object): 2 | x:int = 0 3 | 4 | def __init__(self:"Foo", x:int): 5 | self.x = x 6 | 7 | f = Foo(1) 8 | print(f.x) 9 | -------------------------------------------------------------------------------- /tests/parse/class_method.py: -------------------------------------------------------------------------------- 1 | class Foo(object): 2 | x:int = 0 3 | 4 | def set(self:"Foo", x:int) -> object: 5 | self.x = x 6 | 7 | f = Foo() 8 | f.set(1) 9 | print(f.x) 10 | -------------------------------------------------------------------------------- /tests/parse/coverage.py: -------------------------------------------------------------------------------- 1 | count:int = 0 2 | 3 | def foo(s: str) -> int: 4 | return len(s) 5 | 6 | class bar(object): 7 | p: bool = True 8 | 9 | def baz(self:"bar", xx: [int]) -> str: 10 | global count 11 | x:int = 0 12 | y:int = 1 13 | 14 | def qux(y: int) -> object: 15 | nonlocal x 16 | if x > y: 17 | x = -1 18 | 19 | for x in xx: 20 | self.p = x == 2 21 | 22 | qux(0) # Yay! ChocoPy 23 | 24 | count = count + 1 25 | 26 | while x <= 0: 27 | if self.p: 28 | xx[0] = xx[1] 29 | self.p = not self.p 30 | x = x + 1 31 | elif foo("Long"[0]) == 1: 32 | return self is None 33 | 34 | return "Nope" 35 | 36 | print(bar().baz([1,2])) 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/parse/def_func.py: -------------------------------------------------------------------------------- 1 | def foo() -> int: 2 | return 1 3 | 4 | foo() 5 | -------------------------------------------------------------------------------- /tests/parse/def_func.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 4, 5 ], 4 | "declarations" : [ { 5 | "kind" : "FuncDef", 6 | "location" : [ 1, 1, 2, 12 ], 7 | "name" : { 8 | "kind" : "Identifier", 9 | "location" : [ 1, 5, 1, 7 ], 10 | "name" : "foo" 11 | }, 12 | "params" : [ ], 13 | "returnType" : { 14 | "kind" : "ClassType", 15 | "location" : [ 1, 14, 1, 16 ], 16 | "className" : "int" 17 | }, 18 | "declarations" : [ ], 19 | "statements" : [ { 20 | "kind" : "ReturnStmt", 21 | "location" : [ 2, 5, 2, 12 ], 22 | "value" : { 23 | "kind" : "IntegerLiteral", 24 | "location" : [ 2, 12, 2, 12 ], 25 | "value" : 1 26 | } 27 | } ] 28 | } ], 29 | "statements" : [ { 30 | "kind" : "ExprStmt", 31 | "location" : [ 4, 1, 4, 5 ], 32 | "expr" : { 33 | "kind" : "CallExpr", 34 | "location" : [ 4, 1, 4, 5 ], 35 | "function" : { 36 | "kind" : "Identifier", 37 | "location" : [ 4, 1, 4, 3 ], 38 | "name" : "foo" 39 | }, 40 | "args" : [ ] 41 | } 42 | } ], 43 | "errors" : { 44 | "errors" : [ ], 45 | "kind" : "Errors", 46 | "location" : [ 0, 0, 0, 0 ] 47 | } 48 | } -------------------------------------------------------------------------------- /tests/parse/def_func_args.py: -------------------------------------------------------------------------------- 1 | def foo(x:int, y:int) -> bool: 2 | return x > y 3 | 4 | foo(1,2) 5 | -------------------------------------------------------------------------------- /tests/parse/def_func_global.py: -------------------------------------------------------------------------------- 1 | z:int = 0 2 | 3 | def foo(x:int) -> bool: 4 | global z 5 | return x > z 6 | 7 | foo(1) 8 | -------------------------------------------------------------------------------- /tests/parse/def_func_nested.py: -------------------------------------------------------------------------------- 1 | 2 | def foo(x:int) -> bool: 3 | a:int = 0 4 | b:int = 1 5 | def bar(y: int) -> int: 6 | a:int = 2 7 | return y 8 | return bar(x) > a 9 | 10 | foo(1) 11 | -------------------------------------------------------------------------------- /tests/parse/def_func_nonlocal.py: -------------------------------------------------------------------------------- 1 | 2 | def foo(x:int) -> bool: 3 | a:int = 0 4 | b:int = 1 5 | def bar(y: int) -> int: 6 | nonlocal a 7 | a = 2 8 | return y 9 | return bar(x) > a 10 | 11 | foo(1) 12 | -------------------------------------------------------------------------------- /tests/parse/expr_if.py: -------------------------------------------------------------------------------- 1 | 3 if 1 > 2 else 4 2 | -------------------------------------------------------------------------------- /tests/parse/expr_if.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 17 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 17 ], 8 | "expr" : { 9 | "kind" : "IfExpr", 10 | "location" : [ 1, 1, 1, 17 ], 11 | "condition" : { 12 | "kind" : "BinaryExpr", 13 | "location" : [ 1, 6, 1, 10 ], 14 | "left" : { 15 | "kind" : "IntegerLiteral", 16 | "location" : [ 1, 6, 1, 6 ], 17 | "value" : 1 18 | }, 19 | "operator" : ">", 20 | "right" : { 21 | "kind" : "IntegerLiteral", 22 | "location" : [ 1, 10, 1, 10 ], 23 | "value" : 2 24 | } 25 | }, 26 | "thenExpr" : { 27 | "kind" : "IntegerLiteral", 28 | "location" : [ 1, 1, 1, 1 ], 29 | "value" : 3 30 | }, 31 | "elseExpr" : { 32 | "kind" : "IntegerLiteral", 33 | "location" : [ 1, 17, 1, 17 ], 34 | "value" : 4 35 | } 36 | } 37 | } ], 38 | "errors" : { 39 | "errors" : [ ], 40 | "kind" : "Errors", 41 | "location" : [ 0, 0, 0, 0 ] 42 | } 43 | } -------------------------------------------------------------------------------- /tests/parse/expr_index.py: -------------------------------------------------------------------------------- 1 | a + b[i][j] 2 | -------------------------------------------------------------------------------- /tests/parse/expr_index.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 11 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 11 ], 8 | "expr" : { 9 | "kind" : "BinaryExpr", 10 | "location" : [ 1, 1, 1, 11 ], 11 | "left" : { 12 | "kind" : "Identifier", 13 | "location" : [ 1, 1, 1, 1 ], 14 | "name" : "a" 15 | }, 16 | "operator" : "+", 17 | "right" : { 18 | "kind" : "IndexExpr", 19 | "location" : [ 1, 5, 1, 11 ], 20 | "list" : { 21 | "kind" : "IndexExpr", 22 | "location" : [ 1, 5, 1, 8 ], 23 | "list" : { 24 | "kind" : "Identifier", 25 | "location" : [ 1, 5, 1, 5 ], 26 | "name" : "b" 27 | }, 28 | "index" : { 29 | "kind" : "Identifier", 30 | "location" : [ 1, 7, 1, 7 ], 31 | "name" : "i" 32 | } 33 | }, 34 | "index" : { 35 | "kind" : "Identifier", 36 | "location" : [ 1, 10, 1, 10 ], 37 | "name" : "j" 38 | } 39 | } 40 | } 41 | } ], 42 | "errors" : { 43 | "errors" : [ ], 44 | "kind" : "Errors", 45 | "location" : [ 0, 0, 0, 0 ] 46 | } 47 | } -------------------------------------------------------------------------------- /tests/parse/expr_plus.py: -------------------------------------------------------------------------------- 1 | 1 + 2 + 3 2 | -------------------------------------------------------------------------------- /tests/parse/expr_plus.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 9 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 9 ], 8 | "expr" : { 9 | "kind" : "BinaryExpr", 10 | "location" : [ 1, 1, 1, 9 ], 11 | "left" : { 12 | "kind" : "BinaryExpr", 13 | "location" : [ 1, 1, 1, 5 ], 14 | "left" : { 15 | "kind" : "IntegerLiteral", 16 | "location" : [ 1, 1, 1, 1 ], 17 | "value" : 1 18 | }, 19 | "operator" : "+", 20 | "right" : { 21 | "kind" : "IntegerLiteral", 22 | "location" : [ 1, 5, 1, 5 ], 23 | "value" : 2 24 | } 25 | }, 26 | "operator" : "+", 27 | "right" : { 28 | "kind" : "IntegerLiteral", 29 | "location" : [ 1, 9, 1, 9 ], 30 | "value" : 3 31 | } 32 | } 33 | } ], 34 | "errors" : { 35 | "errors" : [ ], 36 | "kind" : "Errors", 37 | "location" : [ 0, 0, 0, 0 ] 38 | } 39 | } -------------------------------------------------------------------------------- /tests/parse/expr_unary.py: -------------------------------------------------------------------------------- 1 | -1 2 | -------------------------------------------------------------------------------- /tests/parse/expr_unary.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 2 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 2 ], 8 | "expr" : { 9 | "kind" : "UnaryExpr", 10 | "location" : [ 1, 1, 1, 2 ], 11 | "operator" : "-", 12 | "operand" : { 13 | "kind" : "IntegerLiteral", 14 | "location" : [ 1, 2, 1, 2 ], 15 | "value" : 1 16 | } 17 | } 18 | } ], 19 | "errors" : { 20 | "errors" : [ ], 21 | "kind" : "Errors", 22 | "location" : [ 0, 0, 0, 0 ] 23 | } 24 | } -------------------------------------------------------------------------------- /tests/parse/global.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | 3 | x = 2 4 | 5 | print(x) 6 | -------------------------------------------------------------------------------- /tests/parse/global.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 5, 8 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 9 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 9 ], 24 | "value" : 1 25 | } 26 | } ], 27 | "statements" : [ { 28 | "kind" : "AssignStmt", 29 | "location" : [ 3, 1, 3, 5 ], 30 | "targets" : [ { 31 | "kind" : "Identifier", 32 | "location" : [ 3, 1, 3, 1 ], 33 | "name" : "x" 34 | } ], 35 | "value" : { 36 | "kind" : "IntegerLiteral", 37 | "location" : [ 3, 5, 3, 5 ], 38 | "value" : 2 39 | } 40 | }, { 41 | "kind" : "ExprStmt", 42 | "location" : [ 5, 1, 5, 8 ], 43 | "expr" : { 44 | "kind" : "CallExpr", 45 | "location" : [ 5, 1, 5, 8 ], 46 | "function" : { 47 | "kind" : "Identifier", 48 | "location" : [ 5, 1, 5, 5 ], 49 | "name" : "print" 50 | }, 51 | "args" : [ { 52 | "kind" : "Identifier", 53 | "location" : [ 5, 7, 5, 7 ], 54 | "name" : "x" 55 | } ] 56 | } 57 | } ], 58 | "errors" : { 59 | "errors" : [ ], 60 | "kind" : "Errors", 61 | "location" : [ 0, 0, 0, 0 ] 62 | } 63 | } -------------------------------------------------------------------------------- /tests/parse/literals.py: -------------------------------------------------------------------------------- 1 | True 2 | False 3 | 1 4 | None 5 | "This is a string" 6 | [1, 2, 3] 7 | 8 | -------------------------------------------------------------------------------- /tests/parse/literals.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 6, 9 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 4 ], 8 | "expr" : { 9 | "kind" : "BooleanLiteral", 10 | "location" : [ 1, 1, 1, 4 ], 11 | "value" : true 12 | } 13 | }, { 14 | "kind" : "ExprStmt", 15 | "location" : [ 2, 1, 2, 5 ], 16 | "expr" : { 17 | "kind" : "BooleanLiteral", 18 | "location" : [ 2, 1, 2, 5 ], 19 | "value" : false 20 | } 21 | }, { 22 | "kind" : "ExprStmt", 23 | "location" : [ 3, 1, 3, 1 ], 24 | "expr" : { 25 | "kind" : "IntegerLiteral", 26 | "location" : [ 3, 1, 3, 1 ], 27 | "value" : 1 28 | } 29 | }, { 30 | "kind" : "ExprStmt", 31 | "location" : [ 4, 1, 4, 4 ], 32 | "expr" : { 33 | "kind" : "NoneLiteral", 34 | "location" : [ 4, 1, 4, 4 ] 35 | } 36 | }, { 37 | "kind" : "ExprStmt", 38 | "location" : [ 5, 1, 5, 18 ], 39 | "expr" : { 40 | "kind" : "StringLiteral", 41 | "location" : [ 5, 1, 5, 18 ], 42 | "value" : "This is a string" 43 | } 44 | }, { 45 | "kind" : "ExprStmt", 46 | "location" : [ 6, 1, 6, 9 ], 47 | "expr" : { 48 | "kind" : "ListExpr", 49 | "location" : [ 6, 1, 6, 9 ], 50 | "elements" : [ { 51 | "kind" : "IntegerLiteral", 52 | "location" : [ 6, 2, 6, 2 ], 53 | "value" : 1 54 | }, { 55 | "kind" : "IntegerLiteral", 56 | "location" : [ 6, 5, 6, 5 ], 57 | "value" : 2 58 | }, { 59 | "kind" : "IntegerLiteral", 60 | "location" : [ 6, 8, 6, 8 ], 61 | "value" : 3 62 | } ] 63 | } 64 | } ], 65 | "errors" : { 66 | "errors" : [ ], 67 | "kind" : "Errors", 68 | "location" : [ 0, 0, 0, 0 ] 69 | } 70 | } -------------------------------------------------------------------------------- /tests/parse/stmt_call.py: -------------------------------------------------------------------------------- 1 | print(1) 2 | -------------------------------------------------------------------------------- /tests/parse/stmt_call.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 8 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 8 ], 8 | "expr" : { 9 | "kind" : "CallExpr", 10 | "location" : [ 1, 1, 1, 8 ], 11 | "function" : { 12 | "kind" : "Identifier", 13 | "location" : [ 1, 1, 1, 5 ], 14 | "name" : "print" 15 | }, 16 | "args" : [ { 17 | "kind" : "IntegerLiteral", 18 | "location" : [ 1, 7, 1, 7 ], 19 | "value" : 1 20 | } ] 21 | } 22 | } ], 23 | "errors" : { 24 | "errors" : [ ], 25 | "kind" : "Errors", 26 | "location" : [ 0, 0, 0, 0 ] 27 | } 28 | } -------------------------------------------------------------------------------- /tests/parse/stmt_for.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | for x in [1, 2, 3]: 3 | print(x) 4 | 5 | -------------------------------------------------------------------------------- /tests/parse/stmt_for.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 3, 12 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 9 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 9 ], 24 | "value" : 0 25 | } 26 | } ], 27 | "statements" : [ { 28 | "kind" : "ForStmt", 29 | "location" : [ 2, 1, 3, 12 ], 30 | "identifier" : { 31 | "kind" : "Identifier", 32 | "location" : [ 2, 5, 2, 5 ], 33 | "name" : "x" 34 | }, 35 | "iterable" : { 36 | "kind" : "ListExpr", 37 | "location" : [ 2, 10, 2, 18 ], 38 | "elements" : [ { 39 | "kind" : "IntegerLiteral", 40 | "location" : [ 2, 11, 2, 11 ], 41 | "value" : 1 42 | }, { 43 | "kind" : "IntegerLiteral", 44 | "location" : [ 2, 14, 2, 14 ], 45 | "value" : 2 46 | }, { 47 | "kind" : "IntegerLiteral", 48 | "location" : [ 2, 17, 2, 17 ], 49 | "value" : 3 50 | } ] 51 | }, 52 | "body" : [ { 53 | "kind" : "ExprStmt", 54 | "location" : [ 3, 5, 3, 12 ], 55 | "expr" : { 56 | "kind" : "CallExpr", 57 | "location" : [ 3, 5, 3, 12 ], 58 | "function" : { 59 | "kind" : "Identifier", 60 | "location" : [ 3, 5, 3, 9 ], 61 | "name" : "print" 62 | }, 63 | "args" : [ { 64 | "kind" : "Identifier", 65 | "location" : [ 3, 11, 3, 11 ], 66 | "name" : "x" 67 | } ] 68 | } 69 | } ] 70 | } ], 71 | "errors" : { 72 | "errors" : [ ], 73 | "kind" : "Errors", 74 | "location" : [ 0, 0, 0, 0 ] 75 | } 76 | } -------------------------------------------------------------------------------- /tests/parse/stmt_if.py: -------------------------------------------------------------------------------- 1 | if True: 2 | False 3 | 4 | -------------------------------------------------------------------------------- /tests/parse/stmt_if.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 2, 9 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "IfStmt", 7 | "location" : [ 1, 1, 2, 9 ], 8 | "condition" : { 9 | "kind" : "BooleanLiteral", 10 | "location" : [ 1, 4, 1, 7 ], 11 | "value" : true 12 | }, 13 | "thenBody" : [ { 14 | "kind" : "ExprStmt", 15 | "location" : [ 2, 5, 2, 9 ], 16 | "expr" : { 17 | "kind" : "BooleanLiteral", 18 | "location" : [ 2, 5, 2, 9 ], 19 | "value" : false 20 | } 21 | } ], 22 | "elseBody" : [ ] 23 | } ], 24 | "errors" : { 25 | "errors" : [ ], 26 | "kind" : "Errors", 27 | "location" : [ 0, 0, 0, 0 ] 28 | } 29 | } -------------------------------------------------------------------------------- /tests/parse/stmt_if_elif.py: -------------------------------------------------------------------------------- 1 | if 1 > 2: 2 | print(1) 3 | elif 3 == 4: 4 | print(2) 5 | elif True: 6 | print(3) 7 | -------------------------------------------------------------------------------- /tests/parse/stmt_if_elif_else.py: -------------------------------------------------------------------------------- 1 | if 1 > 2: 2 | print(1) 3 | elif 3 == 4: 4 | print(2) 5 | elif True: 6 | print(3) 7 | else: 8 | print(4) 9 | -------------------------------------------------------------------------------- /tests/parse/stmt_ifelse.py: -------------------------------------------------------------------------------- 1 | if True: 2 | False 3 | else: 4 | True 5 | 6 | -------------------------------------------------------------------------------- /tests/parse/stmt_ifelse.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 4, 8 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "IfStmt", 7 | "location" : [ 1, 1, 4, 8 ], 8 | "condition" : { 9 | "kind" : "BooleanLiteral", 10 | "location" : [ 1, 4, 1, 7 ], 11 | "value" : true 12 | }, 13 | "thenBody" : [ { 14 | "kind" : "ExprStmt", 15 | "location" : [ 2, 5, 2, 9 ], 16 | "expr" : { 17 | "kind" : "BooleanLiteral", 18 | "location" : [ 2, 5, 2, 9 ], 19 | "value" : false 20 | } 21 | } ], 22 | "elseBody" : [ { 23 | "kind" : "ExprStmt", 24 | "location" : [ 4, 5, 4, 8 ], 25 | "expr" : { 26 | "kind" : "BooleanLiteral", 27 | "location" : [ 4, 5, 4, 8 ], 28 | "value" : true 29 | } 30 | } ] 31 | } ], 32 | "errors" : { 33 | "errors" : [ ], 34 | "kind" : "Errors", 35 | "location" : [ 0, 0, 0, 0 ] 36 | } 37 | } -------------------------------------------------------------------------------- /tests/parse/stmt_list_assign.py: -------------------------------------------------------------------------------- 1 | x:int = None 2 | 3 | x = [1, 2, 3] 4 | x[0] = x[1] 5 | -------------------------------------------------------------------------------- /tests/parse/stmt_while.py: -------------------------------------------------------------------------------- 1 | while True: 2 | pass 3 | 4 | -------------------------------------------------------------------------------- /tests/parse/stmt_while.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 11 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "WhileStmt", 7 | "location" : [ 1, 1, 1, 11 ], 8 | "condition" : { 9 | "kind" : "BooleanLiteral", 10 | "location" : [ 1, 7, 1, 10 ], 11 | "value" : true 12 | }, 13 | "body" : [ ] 14 | } ], 15 | "errors" : { 16 | "errors" : [ ], 17 | "kind" : "Errors", 18 | "location" : [ 0, 0, 0, 0 ] 19 | } 20 | } -------------------------------------------------------------------------------- /tests/runtime/assignment.py: -------------------------------------------------------------------------------- 1 | x: int = 1 2 | y: int = 2 3 | z: object = None 4 | a: bool = True 5 | b: bool = False 6 | c: str = "" 7 | d: str = "" 8 | 9 | b = a 10 | 11 | assert x != y 12 | x = y 13 | assert x == y 14 | x = 2 15 | y = 2 16 | assert x == y 17 | x = y = 0 18 | assert x == 0 19 | assert y == 0 20 | 21 | 22 | z = None 23 | assert z is None 24 | 25 | assert a == b 26 | b = False 27 | assert a != b 28 | 29 | assert c == d 30 | d = c = "123" 31 | assert c == d 32 | d = "456" 33 | assert c != d 34 | d = "123" 35 | assert c == d 36 | 37 | z = print("1234") 38 | assert z is None 39 | -------------------------------------------------------------------------------- /tests/runtime/binary_tree.py: -------------------------------------------------------------------------------- 1 | # Binary-search trees 2 | class TreeNode(object): 3 | value: int = 0 4 | left: "TreeNode" = None 5 | right: "TreeNode" = None 6 | 7 | def insert(self: "TreeNode", x: int) -> bool: 8 | if x < self.value: 9 | if self.left is None: 10 | self.left = makeNode(x) 11 | return True 12 | else: 13 | return self.left.insert(x) 14 | elif x > self.value: 15 | if self.right is None: 16 | self.right = makeNode(x) 17 | return True 18 | else: 19 | return self.right.insert(x) 20 | return False 21 | 22 | def contains(self: "TreeNode", x: int) -> bool: 23 | if x < self.value: 24 | if self.left is None: 25 | return False 26 | else: 27 | return self.left.contains(x) 28 | elif x > self.value: 29 | if self.right is None: 30 | return False 31 | else: 32 | return self.right.contains(x) 33 | else: 34 | return True 35 | 36 | 37 | class Tree(object): 38 | root: TreeNode = None 39 | size: int = 0 40 | 41 | def insert(self: "Tree", x: int) -> object: 42 | if self.root is None: 43 | self.root = makeNode(x) 44 | self.size = 1 45 | else: 46 | if self.root.insert(x): 47 | self.size = self.size + 1 48 | 49 | def contains(self: "Tree", x: int) -> bool: 50 | if self.root is None: 51 | return False 52 | else: 53 | return self.root.contains(x) 54 | 55 | 56 | def makeNode(x: int) -> TreeNode: 57 | b: TreeNode = None 58 | b = TreeNode() 59 | b.value = x 60 | return b 61 | 62 | 63 | # Input parameters 64 | n: int = 100 65 | c: int = 4 66 | 67 | # Data 68 | t: Tree = None 69 | i: int = 0 70 | k: int = 37813 71 | 72 | # Crunch 73 | t = Tree() 74 | while i < n: 75 | t.insert(k) 76 | k = (k * 37813) % 37831 77 | if i % c != 0: 78 | t.insert(i) 79 | i = i + 1 80 | 81 | assert t.size == 175 82 | assert t.contains(15) 83 | assert t.contains(23) 84 | assert t.contains(42) 85 | assert not t.contains(4) 86 | assert not t.contains(8) 87 | assert not t.contains(16) 88 | -------------------------------------------------------------------------------- /tests/runtime/classes.py: -------------------------------------------------------------------------------- 1 | class A: 2 | y: int = 1 3 | 4 | def __init__(self: A): 5 | pass 6 | 7 | def t(self: A): 8 | global x 9 | x = 1 10 | 11 | 12 | class B(A): 13 | z: int = 0 14 | 15 | def __init__(self: B): 16 | self.z = 5 17 | self.y = 5 18 | 19 | def t(self: B): 20 | global x 21 | x = 2 22 | 23 | def setZ(self: B, z: int): 24 | self.z = z 25 | 26 | 27 | x: int = 0 28 | c1: A = None 29 | c2: B = None 30 | c3: A = None 31 | 32 | # constructors, getters, setters 33 | c1 = A() 34 | assert c1.y == 1 35 | c2 = B() 36 | assert c2.y == 5 37 | assert c2.z == 5 38 | c3 = B() 39 | assert c3.y == 5 40 | 41 | c2.y = 0 42 | assert c2.y == 0 43 | 44 | # methods, dynamic dispatch 45 | 46 | c2.setZ(2) 47 | assert c2.z == 2 48 | 49 | x = 0 50 | c1.t() 51 | assert x == 1 52 | 53 | x = 0 54 | c2.t() 55 | assert x == 2 56 | 57 | x = 0 58 | c3.t() 59 | assert x == 2 60 | -------------------------------------------------------------------------------- /tests/runtime/contains.py: -------------------------------------------------------------------------------- 1 | # Search in a list 2 | def contains(items: [int], x: int) -> bool: 3 | i: int = 0 4 | while i < len(items): 5 | if items[i] == x: 6 | return True 7 | i = i + 1 8 | return False 9 | 10 | 11 | def contains2(items: [int], x: int) -> bool: 12 | i: int = 0 13 | for i in items: 14 | if i == x: 15 | return True 16 | return False 17 | 18 | 19 | assert contains([4, 8, 15, 16, 23], 15) 20 | assert contains([4, 8, 15, 16, 23], 4) 21 | assert contains([4, 8, 15, 16, 23], 8) 22 | assert contains([4, 8, 15, 16, 23], 16) 23 | assert contains([4, 8, 15, 16, 23], 23) 24 | assert not contains([4, 8, 15, 16, 23], 999) 25 | assert not contains([4], 15) 26 | assert not contains([], 15) 27 | 28 | assert contains2([4, 8, 15, 16, 23], 15) 29 | assert contains2([4, 8, 15, 16, 23], 4) 30 | assert contains2([4, 8, 15, 16, 23], 8) 31 | assert contains2([4, 8, 15, 16, 23], 16) 32 | assert contains2([4, 8, 15, 16, 23], 23) 33 | assert not contains2([4, 8, 15, 16, 23], 999) 34 | assert not contains2([4], 15) 35 | assert not contains2([], 15) 36 | -------------------------------------------------------------------------------- /tests/runtime/control_flow.py: -------------------------------------------------------------------------------- 1 | x: [int] = None 2 | y: str = "123" 3 | z: str = "" 4 | char: str = "" 5 | a: bool = True 6 | b: int = 0 7 | c: int = 100 8 | d: [bool] = None 9 | e: object = None 10 | f: [object] = None 11 | 12 | x = [] 13 | 14 | for char in y: 15 | pass 16 | 17 | for char in y: 18 | z = char + z 19 | assert z == "321" 20 | assert char == "3" 21 | 22 | x = [1, 2, 3] 23 | for b in x: 24 | x[0] = b 25 | assert x[0] == 3 26 | 27 | x = [1, 2, 3] 28 | for b in x: 29 | c = c * 2 30 | assert c == 800 31 | assert b == 3 32 | 33 | c = 100 34 | x = [] 35 | for b in x: 36 | c = c * 2 37 | assert c == 100 38 | 39 | a = True 40 | d = [True, True, True, False] 41 | for a in d: 42 | pass 43 | assert not a 44 | 45 | a = True 46 | d = [True, True, True] 47 | for a in d: 48 | assert a 49 | print(a) 50 | 51 | e = None 52 | f = [None, object(), None, object()] 53 | for e in f: 54 | pass 55 | assert not (e is None) 56 | -------------------------------------------------------------------------------- /tests/runtime/control_flow_2.py: -------------------------------------------------------------------------------- 1 | b: int = 0 2 | 3 | 4 | b = 0 5 | if b == 0: 6 | b = 1 7 | assert b == 1 8 | 9 | b = 0 10 | if b != 0: 11 | b = 2 12 | assert b == 0 13 | 14 | b = 0 15 | if b != 0: 16 | b = 0 17 | else: 18 | b = 1 19 | assert b == 1 20 | 21 | b = 0 22 | if b == 0: 23 | b = 1 24 | else: 25 | b = 0 26 | assert b == 1 27 | 28 | b = 0 29 | if b > 0: 30 | b = 0 31 | elif b < 0: 32 | b = 0 33 | else: 34 | b = 1 35 | assert b == 1 36 | 37 | b = 0 38 | if b == 0: 39 | pass 40 | elif b < 0: 41 | b = 1 42 | else: 43 | b = 1 44 | assert b == 0 45 | 46 | b = 5 47 | if b == 0: 48 | b = 1 49 | elif b < 0: 50 | b = 2 51 | else: 52 | pass 53 | assert b == 5 54 | 55 | b = -1 56 | if b > 0: 57 | b = 0 58 | elif b < 0: 59 | b = 1 60 | else: 61 | b = 0 62 | assert b == 1 63 | 64 | b = -1 65 | while b > 0: 66 | b = b - 1 67 | assert b == -1 68 | 69 | b = 5 70 | while b > 0: 71 | b = b - 1 72 | assert b == 0 73 | -------------------------------------------------------------------------------- /tests/runtime/exponent.py: -------------------------------------------------------------------------------- 1 | # Compute x**y 2 | def exp(x: int, y: int) -> int: 3 | a: int = 0 4 | 5 | def f(i: int) -> int: 6 | nonlocal a 7 | 8 | def geta() -> int: 9 | return a 10 | if i <= 0: 11 | return geta() 12 | else: 13 | a = a * x 14 | return f(i-1) 15 | a = 1 16 | return f(y) 17 | 18 | 19 | # Input parameter 20 | n: int = 42 21 | 22 | # Run [0, n] 23 | i: int = 0 24 | 25 | # Crunch 26 | while i <= n: 27 | print(exp(2, i % 31)) 28 | i = i + 1 29 | 30 | assert exp(2, 3) == 8 31 | assert exp(3, 3) == 27 32 | assert exp(3, 4) == 81 33 | assert exp(4, 4) == 256 34 | assert exp(5, 1) == 5 35 | assert exp(1, 99) == 1 36 | -------------------------------------------------------------------------------- /tests/runtime/expr_stmt.py: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | None 4 | "123" 5 | False 6 | -------------------------------------------------------------------------------- /tests/runtime/functions.py: -------------------------------------------------------------------------------- 1 | def f1(): 2 | x: int = 1 3 | 4 | 5 | def f2() -> int: 6 | return 1 7 | 8 | 9 | def f3() -> object: 10 | return None 11 | 12 | 13 | def f4(x: int, y: object) -> int: 14 | return x + 1 15 | 16 | 17 | def f5(): 18 | return None 19 | 20 | 21 | def f6() -> int: 22 | return f4(5, None) 23 | 24 | 25 | def f7() -> int: 26 | x: int = 0 27 | y: int = 0 28 | x = f4(10, None) 29 | y = f6() 30 | return x - y 31 | 32 | 33 | def f8(x: int) -> int: 34 | return x 35 | 36 | 37 | x: int = 0 38 | y: object = None 39 | 40 | f1() 41 | assert f2() == 1 42 | assert f3() is None 43 | assert f4(1, None) == 2 44 | assert f4(f2(), f3()) == 2 45 | assert f5() is None 46 | x = f4(f2(), f3()) 47 | y = f3() 48 | assert f4(x, y) == 3 49 | assert f6() == 6 50 | assert f7() == 5 51 | assert f8(0) == 0 52 | assert f8(1) == 1 53 | assert f8(f7()) == 5 54 | 55 | print(1) 56 | print(True) 57 | -------------------------------------------------------------------------------- /tests/runtime/global_loop.py: -------------------------------------------------------------------------------- 1 | x: int = 1 2 | 3 | 4 | def test(): 5 | y: [int] = None 6 | 7 | def inner(): 8 | global x 9 | for x in y: 10 | pass 11 | y = [1, 2, 3] 12 | inner() 13 | assert x == 3 14 | 15 | 16 | test() 17 | -------------------------------------------------------------------------------- /tests/runtime/globals.py: -------------------------------------------------------------------------------- 1 | x: int = 0 2 | y: str = "a" 3 | z: int = 0 4 | 5 | 6 | def t(): 7 | global x 8 | global y 9 | x = x + 1 10 | y = y + y 11 | assert z == 0 12 | 13 | 14 | assert x == 0 15 | assert y == "a" 16 | t() 17 | assert x == 1 18 | assert y == "aa" 19 | -------------------------------------------------------------------------------- /tests/runtime/hello_world.py: -------------------------------------------------------------------------------- 1 | print("hello, world!") 2 | -------------------------------------------------------------------------------- /tests/runtime/incrementing_counter.py: -------------------------------------------------------------------------------- 1 | class Counter(object): 2 | n: int = 0 3 | 4 | def __init__(self: Counter): 5 | pass 6 | 7 | def inc(self: Counter): 8 | self.n = self.n + 1 9 | 10 | 11 | c: Counter = None 12 | i: int = 0 13 | c = Counter() 14 | c.inc() 15 | assert c.n == 1 16 | c.inc() 17 | assert c.n == 2 18 | c.inc() 19 | c.inc() 20 | assert c.n == 4 21 | 22 | for i in [9, 9, 9, 9, 9, 9]: 23 | c.inc() 24 | assert c.n == 10 25 | -------------------------------------------------------------------------------- /tests/runtime/inherit_init.py: -------------------------------------------------------------------------------- 1 | # this is the same as linked_list.py except LinkedList.__init__ is inherited 2 | 3 | class Link(object): 4 | val: int = 0 5 | next: "Link" = None 6 | 7 | def __init__(self: "Link"): 8 | pass 9 | 10 | def new(self: "Link", val: int, next: "Link") -> "Link": 11 | self.val = val 12 | self.next = next 13 | return self 14 | 15 | 16 | class LinkedList(object): 17 | head: Link = None 18 | 19 | def __init(self: "LinkedList"): 20 | pass 21 | 22 | def is_empty(self: "LinkedList") -> bool: 23 | return self.head is None 24 | 25 | def length(self: "LinkedList") -> int: 26 | cur: Link = None 27 | length: int = 0 28 | cur = self.head 29 | while not (cur is None): 30 | length = length + 1 31 | cur = cur.next 32 | return length 33 | 34 | def add(self: "LinkedList", val: int): 35 | self.head = Link().new(val, self.head) 36 | 37 | 38 | x: LinkedList = None 39 | 40 | x = LinkedList() 41 | assert x.is_empty() 42 | assert x.length() == 0 43 | x.add(1) 44 | assert not x.is_empty() 45 | assert x.length() == 1 46 | assert x.head.val == 1 47 | x.add(100) 48 | assert not x.is_empty() 49 | assert x.length() == 2 50 | assert x.head.val == 100 51 | assert x.head.next.val == 1 52 | -------------------------------------------------------------------------------- /tests/runtime/int_and_bool.py: -------------------------------------------------------------------------------- 1 | x: int = 1 2 | y: int = 2 3 | a: bool = True 4 | b: bool = False 5 | 6 | print(x) 7 | print(y) 8 | print(a) 9 | print(b) 10 | 11 | assert x + y == 3 12 | assert x < y 13 | assert y > x 14 | assert x + x == 2 15 | assert y * y == 4 16 | assert 5 // 2 == y 17 | assert 5 % 2 == x 18 | assert x == x 19 | assert x != y 20 | assert not b 21 | assert a 22 | assert True 23 | assert not False 24 | assert a == a 25 | assert a != b 26 | assert a and a 27 | assert a or b 28 | assert not (b or b) 29 | assert not (b and b) 30 | 31 | x = y 32 | assert x == y 33 | assert x == 2 34 | 35 | x = y = 3 36 | assert x == y 37 | assert x == 3 38 | -------------------------------------------------------------------------------- /tests/runtime/int_and_bool_control_flow.py: -------------------------------------------------------------------------------- 1 | x: int = 1 2 | y: int = 2 3 | a: bool = True 4 | b: bool = False 5 | 6 | if a: 7 | assert True 8 | 9 | if a: 10 | assert True 11 | else: 12 | assert False 13 | 14 | if b: 15 | assert False 16 | 17 | if b: 18 | assert False 19 | else: 20 | assert True 21 | 22 | if x == y: 23 | assert False 24 | else: 25 | assert True 26 | 27 | if x == x: 28 | assert True 29 | else: 30 | assert False 31 | 32 | assert (5 if a else 0) == 5 33 | assert (0 if b else 5) == 5 34 | -------------------------------------------------------------------------------- /tests/runtime/int_and_bool_funcs.py: -------------------------------------------------------------------------------- 1 | x: int = 1 2 | y: int = 2 3 | a: bool = True 4 | b: bool = False 5 | 6 | 7 | def test1(a1: int, a2: int) -> int: 8 | return a1 + a2 9 | 10 | 11 | def test2(a1: bool) -> bool: 12 | return not a1 13 | 14 | 15 | def test3(): 16 | return None 17 | 18 | 19 | def test4(): 20 | return 21 | 22 | 23 | test3() 24 | test4() 25 | 26 | assert test1(x, y) == 3 27 | assert test1(x, x) == 2 28 | assert test2(b) 29 | assert not test2(a) 30 | assert test4() is None 31 | assert test3() is None 32 | -------------------------------------------------------------------------------- /tests/runtime/linked_list.py: -------------------------------------------------------------------------------- 1 | class Link(object): 2 | val: int = 0 3 | next: "Link" = None 4 | 5 | def __init__(self: "Link"): 6 | pass 7 | 8 | def new(self: "Link", val: int, next: "Link") -> "Link": 9 | self.val = val 10 | self.next = next 11 | return self 12 | 13 | 14 | class LinkedList(object): 15 | head: Link = None 16 | 17 | def __init__(self: "LinkedList"): 18 | pass 19 | 20 | def is_empty(self: "LinkedList") -> bool: 21 | return self.head is None 22 | 23 | def length(self: "LinkedList") -> int: 24 | cur: Link = None 25 | length: int = 0 26 | cur = self.head 27 | while not (cur is None): 28 | length = length + 1 29 | cur = cur.next 30 | return length 31 | 32 | def add(self: "LinkedList", val: int): 33 | self.head = Link().new(val, self.head) 34 | 35 | 36 | x: LinkedList = None 37 | 38 | x = LinkedList() 39 | assert x.is_empty() 40 | assert x.length() == 0 41 | x.add(1) 42 | assert not x.is_empty() 43 | assert x.length() == 1 44 | assert x.head.val == 1 45 | x.add(100) 46 | assert not x.is_empty() 47 | assert x.length() == 2 48 | assert x.head.val == 100 49 | assert x.head.next.val == 1 50 | -------------------------------------------------------------------------------- /tests/runtime/local_loop.py: -------------------------------------------------------------------------------- 1 | x: str = "" 2 | y: str = "123" 3 | 4 | for x in y: 5 | pass 6 | 7 | assert x == "3" 8 | -------------------------------------------------------------------------------- /tests/runtime/modulo.py: -------------------------------------------------------------------------------- 1 | assert -5 % 2 == 1 2 | assert 5 % -2 == -1 3 | assert -5 % -2 == -1 4 | 5 | assert -5 % 3 == 1 6 | assert 5 % -3 == -1 7 | assert -5 % -3 == -2 8 | 9 | assert -5 % 1 == 0 10 | assert -5 % -1 == 0 11 | assert 5 % -1 == 0 12 | 13 | assert -5 % 4 == 3 14 | assert -5 % -4 == -1 15 | assert 5 % -4 == -3 16 | 17 | assert -5 % 5 == 0 18 | assert -5 % -5 == 0 19 | assert 5 % -5 == 0 20 | -------------------------------------------------------------------------------- /tests/runtime/nested_list.py: -------------------------------------------------------------------------------- 1 | a: [[int]] = None 2 | b: [int] = None 3 | c: int = 0 4 | d: int = 0 5 | 6 | # TODO - check if these are legal 7 | # a = [] 8 | # assert len(a) == 0 9 | # a = [[]] 10 | # assert len(a) == 1 11 | # assert len(a[0]) == 0 12 | 13 | a = [[1]] 14 | assert len(a) == 1 15 | assert len(a[0]) == 1 16 | 17 | a = [[1], [2, 2, 2], [3, 3], []] 18 | assert len(a) == 4 19 | assert len(a[0]) == 1 20 | assert len(a[1]) == 3 21 | assert len(a[2]) == 2 22 | assert len(a[3]) == 0 23 | 24 | assert a[0][0] == 1 25 | assert a[1][0] == 2 26 | assert a[1][1] == 2 27 | assert a[1][2] == 2 28 | 29 | a[0][0] = 5 30 | assert a[0][0] == 5 31 | 32 | a[0] = [2, 2] 33 | assert len(a[0]) == 2 34 | 35 | a[0] = a[0] + [3] 36 | assert len(a[0]) == 3 37 | 38 | 39 | a = [[1], [1, 1, 1], [1, 1], []] 40 | c = 0 41 | for b in a: 42 | c = c + len(b) 43 | assert c == 6 44 | 45 | a = [[1], [2, 3, 4], [5, 0], []] 46 | c = 0 47 | for b in a: 48 | for d in b: 49 | c = c + d 50 | assert c == 15 51 | -------------------------------------------------------------------------------- /tests/runtime/nonlocal_builtins.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def f(): 4 | x: bool = True 5 | y: str = "a" 6 | 7 | def g(): 8 | nonlocal x 9 | nonlocal y 10 | print(y) 11 | assert x 12 | g() 13 | 14 | 15 | f() 16 | -------------------------------------------------------------------------------- /tests/runtime/nonlocal_loop.py: -------------------------------------------------------------------------------- 1 | def test(): 2 | x: int = 1 3 | y: [int] = None 4 | 5 | def inner(): 6 | nonlocal x 7 | for x in y: 8 | pass 9 | y = [1, 2, 3] 10 | inner() 11 | assert x == 3 12 | 13 | 14 | test() 15 | -------------------------------------------------------------------------------- /tests/runtime/null_and_empty_list_compare.py: -------------------------------------------------------------------------------- 1 | w: [int] = None 2 | assert w is None 3 | assert not w is [] 4 | w = [] 5 | assert not w is None 6 | assert not w is [] 7 | -------------------------------------------------------------------------------- /tests/runtime/operators.py: -------------------------------------------------------------------------------- 1 | w: int = 1 2 | x: int = 1 3 | y: int = 2 4 | z: object = None 5 | a: str = "123" 6 | b: str = "123" 7 | c: str = "456" 8 | assert w == x 9 | assert y != x 10 | assert b == b 11 | assert a == b 12 | assert b != c 13 | assert y > x 14 | assert y >= x 15 | assert w >= x 16 | assert x < y 17 | assert x <= y 18 | assert w <= x 19 | assert w + x == y 20 | assert y - x == w 21 | assert w * x == x 22 | assert 5 // 2 == y 23 | assert 5 % 2 == x 24 | assert not False 25 | assert not (w != x) 26 | assert -x == -1 27 | assert True and True 28 | assert True or False 29 | assert False or True 30 | assert (False or True) and True 31 | assert True if x != y else False 32 | assert False if x == y else True 33 | 34 | assert z is z 35 | assert None is None 36 | assert not (object() is object()) 37 | assert z is None 38 | z = object() 39 | assert z is z 40 | -------------------------------------------------------------------------------- /tests/runtime/ratio.py: -------------------------------------------------------------------------------- 1 | class Rat(object): 2 | n: int = 0 3 | d: int = 0 4 | 5 | def __init__(self: Rat): 6 | pass 7 | 8 | def new(self: Rat, n: int, d: int) -> Rat: 9 | self.n = n 10 | self.d = d 11 | return self 12 | 13 | def mul(self: Rat, other: Rat) -> Rat: 14 | return Rat().new(self.n * other.n, self.d * other.d) 15 | 16 | 17 | r1: Rat = None 18 | r2: Rat = None 19 | r3: Rat = None 20 | r1 = Rat().new(4, 5) 21 | r2 = Rat().new(2, 3) 22 | assert r1.n == 4 23 | assert r1.d == 5 24 | assert r2.n == 2 25 | assert r2.d == 3 26 | 27 | r3 = r1.mul(r2) 28 | assert r3.n == 8 29 | assert r3.d == 15 30 | 31 | r3 = r3.mul(r2).mul(r2) 32 | assert r3.n == 32 33 | assert r3.d == 135 34 | -------------------------------------------------------------------------------- /tests/runtime/short_circuit.py: -------------------------------------------------------------------------------- 1 | def foo() -> bool: 2 | assert False 3 | return True 4 | 5 | 6 | print(True or foo()) 7 | print(False and foo()) 8 | -------------------------------------------------------------------------------- /tests/runtime/simple_list.py: -------------------------------------------------------------------------------- 1 | w: [int] = None 2 | x: int = 0 3 | 4 | w = [] 5 | assert len(w) == 0 6 | 7 | w = [1, 2, 3] 8 | assert len(w) == 3 9 | assert w[0] == 1 10 | assert w[1] == 2 11 | assert w[2] == 3 12 | 13 | print(w[0]) 14 | print(w[1]) 15 | print(w[2]) 16 | 17 | w[1] = 10 18 | assert w[1] == 10 19 | 20 | for x in w: 21 | print(x) 22 | 23 | w = w + [5, 1, 0] 24 | assert len(w) == 6 25 | assert w[3] == 5 26 | assert w[4] == 1 27 | assert w[5] == 0 28 | -------------------------------------------------------------------------------- /tests/runtime/simple_string.py: -------------------------------------------------------------------------------- 1 | x: str = "123" 2 | y: str = "" 3 | z: str = "12345" 4 | char: str = "c" 5 | print(x) 6 | print(y) 7 | print(z) 8 | assert len(x) == 3 9 | assert len(y) == 0 10 | assert len(z) == 5 11 | assert char == char[0] 12 | 13 | print(x[0]) 14 | 15 | for char in y: 16 | print(char) 17 | 18 | for char in z: 19 | print(char) 20 | 21 | assert x[0] == "1" 22 | assert x[1] == "2" 23 | assert x[2] == "3" 24 | 25 | x = x + x[0] 26 | assert x == "1231" 27 | 28 | x = x + "" 29 | assert x == "1231" 30 | 31 | x = "" + x 32 | assert x == "1231" 33 | 34 | assert y == "" 35 | assert y != x 36 | assert x != "321" 37 | assert "123" == "123" 38 | assert x == x 39 | assert "" == "" 40 | assert x != "" 41 | -------------------------------------------------------------------------------- /tests/runtime/strings.py: -------------------------------------------------------------------------------- 1 | x: str = "123" 2 | y: str = "123" 3 | 4 | assert len(x) == 3 5 | assert x == y 6 | assert x == "123" 7 | assert y == x 8 | assert x != "456" 9 | assert x[0] == "1" 10 | assert x[1] == "2" 11 | assert x[2] == "3" 12 | 13 | x = "123" 14 | x = x + "" 15 | assert x == "123" 16 | assert len(x) == 3 17 | assert x[0] == "1" 18 | assert x[1] == "2" 19 | assert x[2] == "3" 20 | 21 | x = "123" 22 | x = "" + x 23 | assert x == "123" 24 | assert len(x) == 3 25 | assert x[0] == "1" 26 | assert x[1] == "2" 27 | assert x[2] == "3" 28 | 29 | x = "123" 30 | x = x + "4" 31 | assert x == "1234" 32 | assert len(x) == 4 33 | assert x[0] == "1" 34 | assert x[1] == "2" 35 | assert x[2] == "3" 36 | assert x[3] == "4" 37 | 38 | x = "123" 39 | x = "0" + x 40 | assert x == "0123" 41 | assert len(x) == 4 42 | 43 | x = "123" 44 | x = x + y 45 | assert x == "123123" 46 | assert y == "123" 47 | assert len(x) == 6 48 | assert len(y) == 3 49 | 50 | x = "123" 51 | x = x + x 52 | assert x == "123123" 53 | assert len(x) == 6 54 | 55 | x = "123" 56 | y = x 57 | x = "0" 58 | assert y == "123" 59 | assert len(x) == 1 60 | assert len(y) == 3 61 | 62 | assert "1" + "2" + "3" + "4" + "5" == "12345" 63 | 64 | x = "123123" 65 | assert x[0] + x[1] + x[2] == x[3] + x[4] + x[5] 66 | -------------------------------------------------------------------------------- /tests/runtime/var_decl.py: -------------------------------------------------------------------------------- 1 | w: object = None 2 | x: str = "mystring" 3 | y: int = 1 4 | z: bool = True 5 | # potentially colliding names 6 | i8: int = 1 7 | i32: int = 1 8 | i64: int = 1 9 | int32: int = 1 10 | int64: int = 1 11 | long: int = 1 12 | string: str = "" 13 | null: str = "" 14 | print(x) 15 | print(y) 16 | print(z) 17 | -------------------------------------------------------------------------------- /tests/typecheck/ast_coverage.py: -------------------------------------------------------------------------------- 1 | count:int = 0 2 | 3 | def foo(s: str) -> int: 4 | return len(s) 5 | 6 | class bar(object): 7 | p: bool = True 8 | 9 | def baz(self:"bar", xx: [int]) -> str: 10 | global count 11 | x:int = 0 12 | y:int = 1 13 | 14 | def qux(y: int) -> object: 15 | nonlocal x 16 | if x > y: 17 | x = -1 18 | 19 | for x in xx: 20 | self.p = x == 2 21 | 22 | qux(0) # Yay! ChocoPy 23 | 24 | count = count + 1 25 | 26 | while x <= 0: 27 | if self.p: 28 | xx[0] = xx[1] 29 | self.p = not self.p 30 | x = x + 1 31 | elif foo("Long"[0]) == 1: 32 | self.p = self is None 33 | 34 | return "Nope" 35 | 36 | print(bar().baz([1,2])) 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/typecheck/bad_assign_expr.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | y:int = 0 3 | z:bool = False 4 | 5 | x = z = 1 # Only one error here (assignment to `x = 1` should succeed) 6 | x = y = None 7 | x = y = [] 8 | x = a = None 9 | x = a = [] 10 | x = y = True 11 | 12 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_attr.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | def foo(self:"A") -> int: 5 | return 0 6 | 7 | class B(A): 8 | x:int = 2 # Bad 9 | foo:str = "" # Bad 10 | 11 | A() 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_attr_type.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = True 3 | 4 | A() 5 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_attr_type.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 4, 4 ], 4 | "declarations" : [ { 5 | "kind" : "ClassDef", 6 | "location" : [ 1, 1, 2, 17 ], 7 | "name" : { 8 | "kind" : "Identifier", 9 | "location" : [ 1, 7, 1, 7 ], 10 | "name" : "A" 11 | }, 12 | "superClass" : { 13 | "kind" : "Identifier", 14 | "location" : [ 1, 9, 1, 14 ], 15 | "name" : "object" 16 | }, 17 | "declarations" : [ { 18 | "kind" : "VarDef", 19 | "location" : [ 2, 5, 2, 16 ], 20 | "var" : { 21 | "kind" : "TypedVar", 22 | "location" : [ 2, 5, 2, 9 ], 23 | "identifier" : { 24 | "kind" : "Identifier", 25 | "location" : [ 2, 5, 2, 5 ], 26 | "name" : "x" 27 | }, 28 | "type" : { 29 | "kind" : "ClassType", 30 | "location" : [ 2, 7, 2, 9 ], 31 | "className" : "int" 32 | } 33 | }, 34 | "value" : { 35 | "kind" : "BooleanLiteral", 36 | "location" : [ 2, 13, 2, 16 ], 37 | "value" : true 38 | } 39 | } ] 40 | } ], 41 | "statements" : [ { 42 | "kind" : "ExprStmt", 43 | "location" : [ 4, 1, 4, 3 ], 44 | "expr" : { 45 | "kind" : "CallExpr", 46 | "location" : [ 4, 1, 4, 3 ], 47 | "function" : { 48 | "kind" : "Identifier", 49 | "location" : [ 4, 1, 4, 1 ], 50 | "name" : "A" 51 | }, 52 | "args" : [ ] 53 | } 54 | } ], 55 | "errors" : { 56 | "errors" : [ ], 57 | "kind" : "Errors", 58 | "location" : [ 0, 0, 0, 0 ] 59 | } 60 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_class_attr_type.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 4, 4 ], 4 | "declarations" : [ { 5 | "kind" : "ClassDef", 6 | "location" : [ 1, 1, 2, 17 ], 7 | "name" : { 8 | "kind" : "Identifier", 9 | "location" : [ 1, 7, 1, 7 ], 10 | "name" : "A" 11 | }, 12 | "superClass" : { 13 | "kind" : "Identifier", 14 | "location" : [ 1, 9, 1, 14 ], 15 | "name" : "object" 16 | }, 17 | "declarations" : [ { 18 | "kind" : "VarDef", 19 | "location" : [ 2, 5, 2, 16 ], 20 | "errorMsg" : "Expected type `int`; got type `bool`", 21 | "var" : { 22 | "kind" : "TypedVar", 23 | "location" : [ 2, 5, 2, 9 ], 24 | "identifier" : { 25 | "kind" : "Identifier", 26 | "location" : [ 2, 5, 2, 5 ], 27 | "name" : "x" 28 | }, 29 | "type" : { 30 | "kind" : "ClassType", 31 | "location" : [ 2, 7, 2, 9 ], 32 | "className" : "int" 33 | } 34 | }, 35 | "value" : { 36 | "kind" : "BooleanLiteral", 37 | "location" : [ 2, 13, 2, 16 ], 38 | "inferredType" : { 39 | "kind" : "ClassValueType", 40 | "className" : "bool" 41 | }, 42 | "value" : true 43 | } 44 | } ] 45 | } ], 46 | "statements" : [ { 47 | "kind" : "ExprStmt", 48 | "location" : [ 4, 1, 4, 3 ], 49 | "expr" : { 50 | "kind" : "CallExpr", 51 | "location" : [ 4, 1, 4, 3 ], 52 | "inferredType" : { 53 | "kind" : "ClassValueType", 54 | "className" : "A" 55 | }, 56 | "function" : { 57 | "kind" : "Identifier", 58 | "location" : [ 4, 1, 4, 1 ], 59 | "name" : "A" 60 | }, 61 | "args" : [ ] 62 | } 63 | } ], 64 | "errors" : { 65 | "errors" : [ { 66 | "kind" : "CompilerError", 67 | "location" : [ 2, 5, 2, 16 ], 68 | "message" : "Expected type `int`; got type `bool`" 69 | } ], 70 | "kind" : "Errors", 71 | "location" : [ 0, 0, 0, 0 ] 72 | } 73 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_class_init_override.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | def __init__(self:"A", x:int): # Bad override 5 | pass 6 | 7 | A(1) 8 | 9 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_init_override2.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | __init__:int = 5 # Bad override 4 | 5 | A() 6 | 7 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_init_override2.py.ast: -------------------------------------------------------------------------------- 1 | {"kind": "Program", "location": [1, 1, 1, 1], "declarations": [{"kind": "ClassDef", "location": [1, 1, 1, 1], "name": {"kind": "Identifier", "location": [1, 7, 1, 7], "name": "A"}, "superClass": {"kind": "Identifier", "location": [1, 9, 1, 9], "name": "object"}, "declarations": [{"kind": "VarDef", "location": [2, 5, 2, 5], "var": {"kind": "TypedVar", "location": [2, 5, 2, 5], "identifier": {"kind": "Identifier", "location": [2, 5, 2, 5], "name": "x"}, "type": {"kind": "ClassType", "location": [2, 7, 2, 7], "className": "int"}}, "value": {"kind": "IntegerLiteral", "location": [2, 13, 2, 13], "value": 1}}, {"kind": "VarDef", "location": [3, 5, 3, 5], "var": {"kind": "TypedVar", "location": [3, 5, 3, 5], "identifier": {"kind": "Identifier", "location": [3, 5, 3, 5], "name": "__init__"}, "type": {"kind": "ClassType", "location": [3, 14, 3, 14], "className": "int"}}, "value": {"kind": "IntegerLiteral", "location": [3, 20, 3, 20], "value": 5}}]}], "statements": [{"kind": "ExprStmt", "location": [5, 1, 5, 1], "expr": {"kind": "CallExpr", "location": [5, 1, 5, 1], "function": {"kind": "Identifier", "location": [5, 1, 5, 1], "name": "A"}, "args": []}}], "errors": {"kind": "Errors", "location": [0, 0, 0, 0], "errors": []}} 2 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_init_override2.py.ast.typed: -------------------------------------------------------------------------------- 1 | {"kind": "Program", "location": [1, 1, 1, 1], "declarations": [{"kind": "ClassDef", "location": [1, 1, 1, 1], "name": {"kind": "Identifier", "location": [1, 7, 1, 7], "name": "A"}, "superClass": {"kind": "Identifier", "location": [1, 9, 1, 9], "name": "object"}, "declarations": [{"kind": "VarDef", "location": [2, 5, 2, 5], "var": {"kind": "TypedVar", "location": [2, 5, 2, 5], "identifier": {"kind": "Identifier", "location": [2, 5, 2, 5], "name": "x"}, "type": {"kind": "ClassType", "location": [2, 7, 2, 7], "className": "int"}}, "value": {"kind": "IntegerLiteral", "location": [2, 13, 2, 13], "inferredType": {"kind": "ClassValueType", "className": "int"}, "value": 1}}, {"kind": "VarDef", "location": [3, 5, 3, 5], "var": {"kind": "TypedVar", "location": [3, 5, 3, 5], "identifier": {"kind": "Identifier", "location": [3, 5, 3, 5], "errorMsg": "Cannot redefine attribute: __init__. Line 3 Col 5", "name": "__init__"}, "type": {"kind": "ClassType", "location": [3, 14, 3, 14], "className": "int"}}, "value": {"kind": "IntegerLiteral", "location": [3, 20, 3, 20], "inferredType": {"kind": "ClassValueType", "className": "int"}, "value": 5}}]}], "statements": [{"kind": "ExprStmt", "location": [5, 1, 5, 1], "expr": {"kind": "CallExpr", "location": [5, 1, 5, 1], "function": {"kind": "Identifier", "location": [5, 1, 5, 1], "name": "A"}, "args": []}}], "errors": {"kind": "Errors", "location": [0, 0, 0, 0], "errors": [{"kind": "CompilerError", "location": [3, 5, 3, 5], "message": "Cannot redefine attribute: __init__. Line 3 Col 5"}]}} 2 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_init_return.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def __init__(self:"A"): 3 | return 1 # Bad 4 | 5 | A() 6 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_init_return.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 5, 4 ], 4 | "declarations" : [ { 5 | "kind" : "ClassDef", 6 | "location" : [ 1, 1, 5, 0 ], 7 | "name" : { 8 | "kind" : "Identifier", 9 | "location" : [ 1, 7, 1, 7 ], 10 | "name" : "A" 11 | }, 12 | "superClass" : { 13 | "kind" : "Identifier", 14 | "location" : [ 1, 9, 1, 14 ], 15 | "name" : "object" 16 | }, 17 | "declarations" : [ { 18 | "kind" : "FuncDef", 19 | "location" : [ 2, 5, 3, 23 ], 20 | "name" : { 21 | "kind" : "Identifier", 22 | "location" : [ 2, 9, 2, 16 ], 23 | "name" : "__init__" 24 | }, 25 | "params" : [ { 26 | "kind" : "TypedVar", 27 | "location" : [ 2, 18, 2, 25 ], 28 | "identifier" : { 29 | "kind" : "Identifier", 30 | "location" : [ 2, 18, 2, 21 ], 31 | "name" : "self" 32 | }, 33 | "type" : { 34 | "kind" : "ClassType", 35 | "location" : [ 2, 23, 2, 25 ], 36 | "className" : "A" 37 | } 38 | } ], 39 | "returnType" : { 40 | "kind" : "ClassType", 41 | "location" : [ 2, 27, 2, 27 ], 42 | "className" : "" 43 | }, 44 | "declarations" : [ ], 45 | "statements" : [ { 46 | "kind" : "ReturnStmt", 47 | "location" : [ 3, 9, 3, 16 ], 48 | "value" : { 49 | "kind" : "IntegerLiteral", 50 | "location" : [ 3, 16, 3, 16 ], 51 | "value" : 1 52 | } 53 | } ] 54 | } ] 55 | } ], 56 | "statements" : [ { 57 | "kind" : "ExprStmt", 58 | "location" : [ 5, 1, 5, 3 ], 59 | "expr" : { 60 | "kind" : "CallExpr", 61 | "location" : [ 5, 1, 5, 3 ], 62 | "function" : { 63 | "kind" : "Identifier", 64 | "location" : [ 5, 1, 5, 1 ], 65 | "name" : "A" 66 | }, 67 | "args" : [ ] 68 | } 69 | } ], 70 | "errors" : { 71 | "errors" : [ ], 72 | "kind" : "Errors", 73 | "location" : [ 0, 0, 0, 0 ] 74 | } 75 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_class_member_expr.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | o:object = None 3 | 4 | x.foo 5 | o.bar 6 | o.baz = 1 7 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_method.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | def foo(self:"A") -> int: # OK 5 | return 0 6 | 7 | def bar() -> int: # Needs self param 8 | return 0 9 | 10 | def baz(self:int) -> int: # Incorrect self type 11 | return 0 12 | 13 | A() 14 | 15 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_method_invoke.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | def get_A(self: "A") -> int: 5 | return self.x 6 | 7 | class B(A): 8 | def __init__(self: "B"): 9 | pass 10 | 11 | class C(B): 12 | z:bool = True 13 | 14 | def set_A(self: "C", val: int) -> object: 15 | self.x = val 16 | 17 | a:A = None 18 | b:B = None 19 | c:C = None 20 | 21 | a = A() 22 | b = B() 23 | c = C() 24 | 25 | a.get_A(1) 26 | b.get_Z() 27 | c.set_A() 28 | c.set_A(False) 29 | c.set_A(None) 30 | 31 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_method_override.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | def foo(self:"A", x:int) -> int: 3 | return x 4 | 5 | def bar(self:"A", x:int) -> int: 6 | return x 7 | 8 | def baz(self:"A", x:int) -> int: 9 | return x 10 | 11 | def qux(self:"A", x:int) -> int: 12 | return x 13 | 14 | class B(A): 15 | 16 | # OK override 17 | def foo(self:"B", x:int) -> int: 18 | return 0 19 | 20 | # Bad override 21 | def bar(self:"B") -> int: 22 | return 0 23 | 24 | # Bad override 25 | def baz(self:"B", x:int) -> bool: 26 | return True 27 | 28 | # Bad override 29 | def qux(self:"B", x:bool) -> int: 30 | return 0 31 | 32 | B() 33 | 34 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_method_override_attr.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | f:int = 3 3 | 4 | class B(A): 5 | def f(self:B) -> int: 6 | return 3 7 | 8 | A() 9 | -------------------------------------------------------------------------------- /tests/typecheck/bad_class_super.py: -------------------------------------------------------------------------------- 1 | # Super is not defined 2 | class A(B): 3 | x:int = 1 4 | 5 | z:int = 2 6 | 7 | # Super is not a class 8 | class B(z): 9 | x:int = 1 10 | 11 | # Cannot extend special classes 12 | class C(int): 13 | x:int = 1 14 | 15 | A() 16 | -------------------------------------------------------------------------------- /tests/typecheck/bad_concat.py: -------------------------------------------------------------------------------- 1 | "Hello" + ["World"] 2 | 1 + [2] 3 | [] + [1] 4 | -------------------------------------------------------------------------------- /tests/typecheck/bad_concat.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 3, 9 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 19 ], 8 | "expr" : { 9 | "kind" : "BinaryExpr", 10 | "location" : [ 1, 1, 1, 19 ], 11 | "left" : { 12 | "kind" : "StringLiteral", 13 | "location" : [ 1, 1, 1, 7 ], 14 | "value" : "Hello" 15 | }, 16 | "operator" : "+", 17 | "right" : { 18 | "kind" : "ListExpr", 19 | "location" : [ 1, 11, 1, 19 ], 20 | "elements" : [ { 21 | "kind" : "StringLiteral", 22 | "location" : [ 1, 12, 1, 18 ], 23 | "value" : "World" 24 | } ] 25 | } 26 | } 27 | }, { 28 | "kind" : "ExprStmt", 29 | "location" : [ 2, 1, 2, 7 ], 30 | "expr" : { 31 | "kind" : "BinaryExpr", 32 | "location" : [ 2, 1, 2, 7 ], 33 | "left" : { 34 | "kind" : "IntegerLiteral", 35 | "location" : [ 2, 1, 2, 1 ], 36 | "value" : 1 37 | }, 38 | "operator" : "+", 39 | "right" : { 40 | "kind" : "ListExpr", 41 | "location" : [ 2, 5, 2, 7 ], 42 | "elements" : [ { 43 | "kind" : "IntegerLiteral", 44 | "location" : [ 2, 6, 2, 6 ], 45 | "value" : 2 46 | } ] 47 | } 48 | } 49 | }, { 50 | "kind" : "ExprStmt", 51 | "location" : [ 3, 1, 3, 8 ], 52 | "expr" : { 53 | "kind" : "BinaryExpr", 54 | "location" : [ 3, 1, 3, 8 ], 55 | "left" : { 56 | "kind" : "ListExpr", 57 | "location" : [ 3, 1, 3, 2 ], 58 | "elements" : [ ] 59 | }, 60 | "operator" : "+", 61 | "right" : { 62 | "kind" : "ListExpr", 63 | "location" : [ 3, 6, 3, 8 ], 64 | "elements" : [ { 65 | "kind" : "IntegerLiteral", 66 | "location" : [ 3, 7, 3, 7 ], 67 | "value" : 1 68 | } ] 69 | } 70 | } 71 | } ], 72 | "errors" : { 73 | "errors" : [ ], 74 | "kind" : "Errors", 75 | "location" : [ 0, 0, 0, 0 ] 76 | } 77 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_duplicate_class.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | z:bool = True 5 | 6 | # Duplicate 7 | class A(object): 8 | x:int = 1 9 | 10 | # Duplicate 11 | class str(object): 12 | x:int = 1 13 | 14 | # Duplicate 15 | class z(object): 16 | x:int = 1 17 | 18 | A() 19 | -------------------------------------------------------------------------------- /tests/typecheck/bad_duplicate_class_member.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 # OK 3 | 4 | def foo(self: "A") -> int: # OK 5 | return 0 6 | 7 | x:int = 1 # Duplicate 8 | 9 | def foo(self: "A") -> int: # Duplicate 10 | return 0 11 | 12 | A() 13 | -------------------------------------------------------------------------------- /tests/typecheck/bad_duplicate_global.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | 3 | def foo() -> object: 4 | pass 5 | 6 | # `foo` cannot be redefined in the same scope 7 | def foo() -> object: 8 | pass 9 | 10 | # `print` cannot be redefined in the same scope 11 | def print(val:object) -> object: 12 | pass 13 | 14 | # `x` cannot be redefined in the same scope 15 | x:int = 2 16 | 17 | 18 | foo() 19 | -------------------------------------------------------------------------------- /tests/typecheck/bad_duplicate_global_2.py: -------------------------------------------------------------------------------- 1 | class x(object): 2 | def x(self:"x") -> int: 3 | return 1 4 | 5 | x:int = 5 6 | 7 | pass 8 | -------------------------------------------------------------------------------- /tests/typecheck/bad_duplicate_global_2.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 7, 5 ], 4 | "declarations" : [ { 5 | "kind" : "ClassDef", 6 | "location" : [ 1, 1, 5, 0 ], 7 | "name" : { 8 | "kind" : "Identifier", 9 | "location" : [ 1, 7, 1, 7 ], 10 | "name" : "x" 11 | }, 12 | "superClass" : { 13 | "kind" : "Identifier", 14 | "location" : [ 1, 9, 1, 14 ], 15 | "name" : "object" 16 | }, 17 | "declarations" : [ { 18 | "kind" : "FuncDef", 19 | "location" : [ 2, 3, 3, 13 ], 20 | "name" : { 21 | "kind" : "Identifier", 22 | "location" : [ 2, 7, 2, 7 ], 23 | "name" : "x" 24 | }, 25 | "params" : [ { 26 | "kind" : "TypedVar", 27 | "location" : [ 2, 9, 2, 16 ], 28 | "identifier" : { 29 | "kind" : "Identifier", 30 | "location" : [ 2, 9, 2, 12 ], 31 | "name" : "self" 32 | }, 33 | "type" : { 34 | "kind" : "ClassType", 35 | "location" : [ 2, 14, 2, 16 ], 36 | "className" : "x" 37 | } 38 | } ], 39 | "returnType" : { 40 | "kind" : "ClassType", 41 | "location" : [ 2, 22, 2, 24 ], 42 | "className" : "int" 43 | }, 44 | "declarations" : [ ], 45 | "statements" : [ { 46 | "kind" : "ReturnStmt", 47 | "location" : [ 3, 5, 3, 12 ], 48 | "value" : { 49 | "kind" : "IntegerLiteral", 50 | "location" : [ 3, 12, 3, 12 ], 51 | "value" : 1 52 | } 53 | } ] 54 | } ] 55 | }, { 56 | "kind" : "VarDef", 57 | "location" : [ 5, 1, 5, 9 ], 58 | "var" : { 59 | "kind" : "TypedVar", 60 | "location" : [ 5, 1, 5, 5 ], 61 | "identifier" : { 62 | "kind" : "Identifier", 63 | "location" : [ 5, 1, 5, 1 ], 64 | "name" : "x" 65 | }, 66 | "type" : { 67 | "kind" : "ClassType", 68 | "location" : [ 5, 3, 5, 5 ], 69 | "className" : "int" 70 | } 71 | }, 72 | "value" : { 73 | "kind" : "IntegerLiteral", 74 | "location" : [ 5, 9, 5, 9 ], 75 | "value" : 5 76 | } 77 | } ], 78 | "statements" : [ ], 79 | "errors" : { 80 | "errors" : [ ], 81 | "kind" : "Errors", 82 | "location" : [ 0, 0, 0, 0 ] 83 | } 84 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_duplicate_global_3.py: -------------------------------------------------------------------------------- 1 | x:int = 4 2 | 3 | class x(object): 4 | def x(self:"x") -> int: 5 | return 1 6 | 7 | pass 8 | -------------------------------------------------------------------------------- /tests/typecheck/bad_duplicate_local.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | y:int = 2 3 | z:int = 3 4 | 5 | def foo(x:int) -> object: 6 | y:int = 4 # OK 7 | x:int = 5 # Duplicate declaration 8 | global z # OK 9 | global y # Duplicate declaration 10 | 11 | def x() -> int: # Duplicate declaration 12 | return 0 13 | 14 | pass 15 | 16 | def bar(x:int, x:int) -> int: # Duplicate params 17 | return x 18 | 19 | 20 | foo(1) 21 | 22 | -------------------------------------------------------------------------------- /tests/typecheck/bad_expr_binary.py: -------------------------------------------------------------------------------- 1 | 1 and 2 2 | 1 or 2 3 | True - False 4 | True < False 5 | 1 + True 6 | False + 0 7 | 1 == True 8 | False != 0 9 | 1 is 1 10 | True is False 11 | None + None 12 | None == None 13 | None is None 14 | -------------------------------------------------------------------------------- /tests/typecheck/bad_expr_if.py: -------------------------------------------------------------------------------- 1 | x: int = 0 2 | x = "Hello" if 2 > 3 else 3 3 | -------------------------------------------------------------------------------- /tests/typecheck/bad_expr_if.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 2, 28 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 10 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 6 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 4, 1, 6 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 10, 1, 10 ], 24 | "value" : 0 25 | } 26 | } ], 27 | "statements" : [ { 28 | "kind" : "AssignStmt", 29 | "location" : [ 2, 1, 2, 27 ], 30 | "targets" : [ { 31 | "kind" : "Identifier", 32 | "location" : [ 2, 1, 2, 1 ], 33 | "name" : "x" 34 | } ], 35 | "value" : { 36 | "kind" : "IfExpr", 37 | "location" : [ 2, 5, 2, 27 ], 38 | "condition" : { 39 | "kind" : "BinaryExpr", 40 | "location" : [ 2, 16, 2, 20 ], 41 | "left" : { 42 | "kind" : "IntegerLiteral", 43 | "location" : [ 2, 16, 2, 16 ], 44 | "value" : 2 45 | }, 46 | "operator" : ">", 47 | "right" : { 48 | "kind" : "IntegerLiteral", 49 | "location" : [ 2, 20, 2, 20 ], 50 | "value" : 3 51 | } 52 | }, 53 | "thenExpr" : { 54 | "kind" : "StringLiteral", 55 | "location" : [ 2, 5, 2, 11 ], 56 | "value" : "Hello" 57 | }, 58 | "elseExpr" : { 59 | "kind" : "IntegerLiteral", 60 | "location" : [ 2, 27, 2, 27 ], 61 | "value" : 3 62 | } 63 | } 64 | } ], 65 | "errors" : { 66 | "errors" : [ ], 67 | "kind" : "Errors", 68 | "location" : [ 0, 0, 0, 0 ] 69 | } 70 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_expr_unary.py: -------------------------------------------------------------------------------- 1 | not "Bad" 2 | -True 3 | -None 4 | not [] 5 | -------------------------------------------------------------------------------- /tests/typecheck/bad_expr_unary.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 4, 7 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 9 ], 8 | "expr" : { 9 | "kind" : "UnaryExpr", 10 | "location" : [ 1, 1, 1, 9 ], 11 | "operator" : "not", 12 | "operand" : { 13 | "kind" : "StringLiteral", 14 | "location" : [ 1, 5, 1, 9 ], 15 | "value" : "Bad" 16 | } 17 | } 18 | }, { 19 | "kind" : "ExprStmt", 20 | "location" : [ 2, 1, 2, 5 ], 21 | "expr" : { 22 | "kind" : "UnaryExpr", 23 | "location" : [ 2, 1, 2, 5 ], 24 | "operator" : "-", 25 | "operand" : { 26 | "kind" : "BooleanLiteral", 27 | "location" : [ 2, 2, 2, 5 ], 28 | "value" : true 29 | } 30 | } 31 | }, { 32 | "kind" : "ExprStmt", 33 | "location" : [ 3, 1, 3, 5 ], 34 | "expr" : { 35 | "kind" : "UnaryExpr", 36 | "location" : [ 3, 1, 3, 5 ], 37 | "operator" : "-", 38 | "operand" : { 39 | "kind" : "NoneLiteral", 40 | "location" : [ 3, 2, 3, 5 ] 41 | } 42 | } 43 | }, { 44 | "kind" : "ExprStmt", 45 | "location" : [ 4, 1, 4, 6 ], 46 | "expr" : { 47 | "kind" : "UnaryExpr", 48 | "location" : [ 4, 1, 4, 6 ], 49 | "operator" : "not", 50 | "operand" : { 51 | "kind" : "ListExpr", 52 | "location" : [ 4, 5, 4, 6 ], 53 | "elements" : [ ] 54 | } 55 | } 56 | } ], 57 | "errors" : { 58 | "errors" : [ ], 59 | "kind" : "Errors", 60 | "location" : [ 0, 0, 0, 0 ] 61 | } 62 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_func_def_call.py: -------------------------------------------------------------------------------- 1 | def foo(x:str, y:bool) -> int: 2 | return bar() 3 | 4 | def bar() -> int: 5 | return 1 6 | 7 | # All of the below are bad calls 8 | foo("Hello") 9 | foo("Hello", False, 3) 10 | foo("Hello", 3) 11 | foo(1, "Hello") 12 | baz() 13 | 14 | -------------------------------------------------------------------------------- /tests/typecheck/bad_func_def_return.py: -------------------------------------------------------------------------------- 1 | def foo(x:str, y:bool) -> int: 2 | return None 3 | 4 | def bar() -> bool: 5 | return 1 6 | 7 | def baz() -> str: 8 | return 9 | 10 | foo("Hello", False) 11 | -------------------------------------------------------------------------------- /tests/typecheck/bad_list_assign.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | y:[object] = None 3 | 4 | x = [1, 2, 3] 5 | y = x 6 | y = [1] 7 | -------------------------------------------------------------------------------- /tests/typecheck/bad_list_index.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [1, 2, 3] 4 | x[True] # Bad 5 | False[0] # Bad 6 | [][0] # Bad 7 | x[True] = x[False] = 1 8 | -------------------------------------------------------------------------------- /tests/typecheck/bad_local_assign.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | y:int = 2 3 | z:int = 3 4 | 5 | def foo(x:int) -> object: 6 | y:int = 4 # OK 7 | global z # OK 8 | 9 | def qux() -> int: 10 | y = 1 # Bad, nonlocal not declared 11 | return 0 12 | 13 | z = 1 # OK 14 | 15 | pass 16 | 17 | def bar(x:int) -> int: 18 | z = 1 # Bad, global not declared 19 | return x 20 | 21 | 22 | foo(1) 23 | 24 | -------------------------------------------------------------------------------- /tests/typecheck/bad_none_assign.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | y:[bool] = None 5 | z:str = "" 6 | a:A = None 7 | 8 | a = A() 9 | 10 | # Cannot assign None to integer/bool/str types 11 | z = None 12 | a.x = None 13 | y[0] = None 14 | 15 | -------------------------------------------------------------------------------- /tests/typecheck/bad_nonlocal_global.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | y:int = 2 3 | z:int = 3 4 | 5 | def foo() -> object: 6 | global x # OK 7 | nonlocal y # No such nonlocal var 8 | global w # No such global var 9 | global int # No such global var 10 | 11 | z:bool = True # OK 12 | 13 | def bar() -> object: 14 | global x # OK 15 | nonlocal z # OK 16 | nonlocal y # No such nonlocal var 17 | global foo # No such global var 18 | nonlocal bar # No such nonlocal var 19 | 20 | pass 21 | 22 | bar() 23 | 24 | foo() 25 | 26 | -------------------------------------------------------------------------------- /tests/typecheck/bad_return_missing.py: -------------------------------------------------------------------------------- 1 | def foo() -> int: 2 | if True: 3 | return 1 4 | # Bad: all paths MUST return int 5 | 6 | foo() 7 | -------------------------------------------------------------------------------- /tests/typecheck/bad_return_missing.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 6, 6 ], 4 | "declarations" : [ { 5 | "kind" : "FuncDef", 6 | "location" : [ 1, 1, 6, 0 ], 7 | "name" : { 8 | "kind" : "Identifier", 9 | "location" : [ 1, 5, 1, 7 ], 10 | "name" : "foo" 11 | }, 12 | "params" : [ ], 13 | "returnType" : { 14 | "kind" : "ClassType", 15 | "location" : [ 1, 14, 1, 16 ], 16 | "className" : "int" 17 | }, 18 | "declarations" : [ ], 19 | "statements" : [ { 20 | "kind" : "IfStmt", 21 | "location" : [ 2, 5, 6, 0 ], 22 | "condition" : { 23 | "kind" : "BooleanLiteral", 24 | "location" : [ 2, 8, 2, 11 ], 25 | "value" : true 26 | }, 27 | "thenBody" : [ { 28 | "kind" : "ReturnStmt", 29 | "location" : [ 3, 9, 3, 16 ], 30 | "value" : { 31 | "kind" : "IntegerLiteral", 32 | "location" : [ 3, 16, 3, 16 ], 33 | "value" : 1 34 | } 35 | } ], 36 | "elseBody" : [ ] 37 | } ] 38 | } ], 39 | "statements" : [ { 40 | "kind" : "ExprStmt", 41 | "location" : [ 6, 1, 6, 5 ], 42 | "expr" : { 43 | "kind" : "CallExpr", 44 | "location" : [ 6, 1, 6, 5 ], 45 | "function" : { 46 | "kind" : "Identifier", 47 | "location" : [ 6, 1, 6, 3 ], 48 | "name" : "foo" 49 | }, 50 | "args" : [ ] 51 | } 52 | } ], 53 | "errors" : { 54 | "errors" : [ ], 55 | "kind" : "Errors", 56 | "location" : [ 0, 0, 0, 0 ] 57 | } 58 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_return_top.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | 3 | return x 4 | -------------------------------------------------------------------------------- /tests/typecheck/bad_return_top.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 3, 9 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 9 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 9 ], 24 | "value" : 0 25 | } 26 | } ], 27 | "statements" : [ { 28 | "kind" : "ReturnStmt", 29 | "location" : [ 3, 1, 3, 8 ], 30 | "value" : { 31 | "kind" : "Identifier", 32 | "location" : [ 3, 8, 3, 8 ], 33 | "name" : "x" 34 | } 35 | } ], 36 | "errors" : { 37 | "errors" : [ ], 38 | "kind" : "Errors", 39 | "location" : [ 0, 0, 0, 0 ] 40 | } 41 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_return_top.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 3, 9 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 9 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 9 ], 24 | "inferredType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "int" 27 | }, 28 | "value" : 0 29 | } 30 | } ], 31 | "statements" : [ { 32 | "kind" : "ReturnStmt", 33 | "location" : [ 3, 1, 3, 8 ], 34 | "errorMsg" : "Return statement cannot appear at the top level", 35 | "value" : { 36 | "kind" : "Identifier", 37 | "location" : [ 3, 8, 3, 8 ], 38 | "name" : "x" 39 | } 40 | } ], 41 | "errors" : { 42 | "errors" : [ { 43 | "kind" : "CompilerError", 44 | "location" : [ 3, 1, 3, 8 ], 45 | "message" : "Return statement cannot appear at the top level" 46 | } ], 47 | "kind" : "Errors", 48 | "location" : [ 0, 0, 0, 0 ] 49 | } 50 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_shadow_local.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | def foo(x:int, bool:str) -> object: # Second param uses an invalid name 5 | y:int = 4 # OK 6 | A:int = 5 # Invalid name 7 | object:str = "" # Invalid name 8 | 9 | def str() -> bool: # Invalid name 10 | return False 11 | 12 | pass 13 | 14 | pass 15 | -------------------------------------------------------------------------------- /tests/typecheck/bad_shadow_local_2.py: -------------------------------------------------------------------------------- 1 | def foo(x:int) -> object: 2 | A:int = 5 # Invalid name 3 | pass 4 | 5 | class A(object): 6 | x:int = 1 7 | 8 | pass 9 | -------------------------------------------------------------------------------- /tests/typecheck/bad_strings.py: -------------------------------------------------------------------------------- 1 | x:str = "Hello" 2 | y:str = "World" 3 | z:str = "" 4 | 5 | 1 + x 6 | z = x + 1 7 | z = x[0] = y 8 | x[1] = y 9 | x[True] 10 | 11 | -------------------------------------------------------------------------------- /tests/typecheck/bad_type_annotation.py: -------------------------------------------------------------------------------- 1 | x:A = None 2 | 3 | def foo(x:B) -> C: 4 | y:D = None 5 | return 6 | 7 | pass 8 | -------------------------------------------------------------------------------- /tests/typecheck/bad_type_id.py: -------------------------------------------------------------------------------- 1 | x - 1 2 | -------------------------------------------------------------------------------- /tests/typecheck/bad_type_id.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 6 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 5 ], 8 | "expr" : { 9 | "kind" : "BinaryExpr", 10 | "location" : [ 1, 1, 1, 5 ], 11 | "left" : { 12 | "kind" : "Identifier", 13 | "location" : [ 1, 1, 1, 1 ], 14 | "name" : "x" 15 | }, 16 | "operator" : "-", 17 | "right" : { 18 | "kind" : "IntegerLiteral", 19 | "location" : [ 1, 5, 1, 5 ], 20 | "value" : 1 21 | } 22 | } 23 | } ], 24 | "errors" : { 25 | "errors" : [ ], 26 | "kind" : "Errors", 27 | "location" : [ 0, 0, 0, 0 ] 28 | } 29 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_type_id.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 6 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 5 ], 8 | "expr" : { 9 | "kind" : "BinaryExpr", 10 | "location" : [ 1, 1, 1, 5 ], 11 | "errorMsg" : "Cannot apply operator `-` on types `object` and `int`", 12 | "inferredType" : { 13 | "kind" : "ClassValueType", 14 | "className" : "int" 15 | }, 16 | "left" : { 17 | "kind" : "Identifier", 18 | "location" : [ 1, 1, 1, 1 ], 19 | "errorMsg" : "Not a variable: x", 20 | "inferredType" : { 21 | "kind" : "ClassValueType", 22 | "className" : "object" 23 | }, 24 | "name" : "x" 25 | }, 26 | "operator" : "-", 27 | "right" : { 28 | "kind" : "IntegerLiteral", 29 | "location" : [ 1, 5, 1, 5 ], 30 | "inferredType" : { 31 | "kind" : "ClassValueType", 32 | "className" : "int" 33 | }, 34 | "value" : 1 35 | } 36 | } 37 | } ], 38 | "errors" : { 39 | "errors" : [ { 40 | "kind" : "CompilerError", 41 | "location" : [ 1, 1, 1, 1 ], 42 | "message" : "Not a variable: x" 43 | }, { 44 | "kind" : "CompilerError", 45 | "location" : [ 1, 1, 1, 5 ], 46 | "message" : "Cannot apply operator `-` on types `object` and `int`" 47 | } ], 48 | "kind" : "Errors", 49 | "location" : [ 0, 0, 0, 0 ] 50 | } 51 | } -------------------------------------------------------------------------------- /tests/typecheck/bad_var_assign.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | y:bool = True 3 | 4 | x = False 5 | y = 2 6 | z = 3 7 | x = z = 4 8 | x = z = None 9 | -------------------------------------------------------------------------------- /tests/typecheck/call.py: -------------------------------------------------------------------------------- 1 | def f() -> int: 2 | print("start f") 3 | g() 4 | print("end f") 5 | return 42 6 | 7 | 8 | def g() -> object: 9 | print("start g") 10 | h() 11 | print("end g") 12 | 13 | def h() -> object: 14 | print("start h") 15 | print("end h") 16 | 17 | print(f()) 18 | -------------------------------------------------------------------------------- /tests/typecheck/call_with_args.py: -------------------------------------------------------------------------------- 1 | def f(x:int) -> int: 2 | print("start f") 3 | print(x) 4 | g(1, x) 5 | print("end f") 6 | return x 7 | 8 | 9 | def g(y:int, z:int) -> object: 10 | print("start g") 11 | print(y) 12 | print(z) 13 | h("h") 14 | print("end g") 15 | 16 | def h(msg: str) -> object: 17 | print(msg) 18 | 19 | print(f(4)) 20 | -------------------------------------------------------------------------------- /tests/typecheck/class_def_assign.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | class B(A): 5 | def __init__(self: "B"): 6 | pass 7 | 8 | class C(B): 9 | z:bool = True 10 | 11 | a:A = None 12 | b:B = None 13 | c:C = None 14 | 15 | a = A() 16 | a = B() 17 | b = a = c = C() 18 | c = None 19 | -------------------------------------------------------------------------------- /tests/typecheck/class_def_attr.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | class B(A): 5 | def __init__(self: "B"): 6 | pass 7 | 8 | class C(B): 9 | z:bool = True 10 | 11 | a:A = None 12 | b:B = None 13 | c:C = None 14 | 15 | a = A() 16 | b = B() 17 | c = C() 18 | 19 | a.x = 1 20 | b.x = a.x 21 | c.z = a.x == b.x 22 | 23 | -------------------------------------------------------------------------------- /tests/typecheck/class_def_init.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | class B(A): 5 | def __init__(self: "B"): 6 | pass 7 | 8 | class C(B): 9 | z:bool = True 10 | 11 | a:A = None 12 | b:B = None 13 | c:C = None 14 | 15 | a = A() 16 | b = B() 17 | c = C() 18 | -------------------------------------------------------------------------------- /tests/typecheck/class_def_methods.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | x:int = 1 3 | 4 | def get_A(self: "A") -> int: 5 | return self.x 6 | 7 | class B(A): 8 | def __init__(self: "B"): 9 | pass 10 | 11 | class C(B): 12 | z:bool = True 13 | 14 | def set_A(self: "C", val: int) -> object: 15 | self.x = val 16 | 17 | a:A = None 18 | b:B = None 19 | c:C = None 20 | 21 | a = A() 22 | b = B() 23 | c = C() 24 | 25 | b.x = a.get_A() 26 | a.x = b.get_A() 27 | c.set_A(0) 28 | 29 | -------------------------------------------------------------------------------- /tests/typecheck/decl_global_forward.py: -------------------------------------------------------------------------------- 1 | def set_x() -> int: 2 | global x 3 | x = 1 4 | return x 5 | 6 | x:int = 0 7 | 8 | set_x() 9 | print(x) 10 | -------------------------------------------------------------------------------- /tests/typecheck/decl_nonlocal_forward.py: -------------------------------------------------------------------------------- 1 | def outer() -> int: 2 | def inner() -> int: 3 | nonlocal x 4 | x = 1 5 | return x 6 | x:int = 0 7 | inner() 8 | return x 9 | 10 | print(outer()) 11 | -------------------------------------------------------------------------------- /tests/typecheck/error_div_zero.py: -------------------------------------------------------------------------------- 1 | print(42 // 0) 2 | -------------------------------------------------------------------------------- /tests/typecheck/error_div_zero.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 15 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 14 ], 8 | "expr" : { 9 | "kind" : "CallExpr", 10 | "location" : [ 1, 1, 1, 14 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "" 14 | }, 15 | "function" : { 16 | "kind" : "Identifier", 17 | "location" : [ 1, 1, 1, 5 ], 18 | "inferredType" : { 19 | "kind" : "FuncType", 20 | "parameters" : [ { 21 | "kind" : "ClassValueType", 22 | "className" : "object" 23 | } ], 24 | "returnType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "" 27 | } 28 | }, 29 | "name" : "print" 30 | }, 31 | "args" : [ { 32 | "kind" : "BinaryExpr", 33 | "location" : [ 1, 7, 1, 13 ], 34 | "inferredType" : { 35 | "kind" : "ClassValueType", 36 | "className" : "int" 37 | }, 38 | "left" : { 39 | "kind" : "IntegerLiteral", 40 | "location" : [ 1, 7, 1, 8 ], 41 | "inferredType" : { 42 | "kind" : "ClassValueType", 43 | "className" : "int" 44 | }, 45 | "value" : 42 46 | }, 47 | "operator" : "//", 48 | "right" : { 49 | "kind" : "IntegerLiteral", 50 | "location" : [ 1, 13, 1, 13 ], 51 | "inferredType" : { 52 | "kind" : "ClassValueType", 53 | "className" : "int" 54 | }, 55 | "value" : 0 56 | } 57 | } ] 58 | } 59 | } ], 60 | "errors" : { 61 | "errors" : [ ], 62 | "kind" : "Errors", 63 | "location" : [ 0, 0, 0, 0 ] 64 | } 65 | } -------------------------------------------------------------------------------- /tests/typecheck/error_invalid_print.py: -------------------------------------------------------------------------------- 1 | print(None) 2 | -------------------------------------------------------------------------------- /tests/typecheck/error_invalid_print.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 12 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 11 ], 8 | "expr" : { 9 | "kind" : "CallExpr", 10 | "location" : [ 1, 1, 1, 11 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "" 14 | }, 15 | "function" : { 16 | "kind" : "Identifier", 17 | "location" : [ 1, 1, 1, 5 ], 18 | "inferredType" : { 19 | "kind" : "FuncType", 20 | "parameters" : [ { 21 | "kind" : "ClassValueType", 22 | "className" : "object" 23 | } ], 24 | "returnType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "" 27 | } 28 | }, 29 | "name" : "print" 30 | }, 31 | "args" : [ { 32 | "kind" : "NoneLiteral", 33 | "location" : [ 1, 7, 1, 10 ], 34 | "inferredType" : { 35 | "kind" : "ClassValueType", 36 | "className" : "" 37 | } 38 | } ] 39 | } 40 | } ], 41 | "errors" : { 42 | "errors" : [ ], 43 | "kind" : "Errors", 44 | "location" : [ 0, 0, 0, 0 ] 45 | } 46 | } -------------------------------------------------------------------------------- /tests/typecheck/error_mod_zero.py: -------------------------------------------------------------------------------- 1 | print(42 % 0) 2 | -------------------------------------------------------------------------------- /tests/typecheck/error_mod_zero.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 14 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 13 ], 8 | "expr" : { 9 | "kind" : "CallExpr", 10 | "location" : [ 1, 1, 1, 13 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "" 14 | }, 15 | "function" : { 16 | "kind" : "Identifier", 17 | "location" : [ 1, 1, 1, 5 ], 18 | "inferredType" : { 19 | "kind" : "FuncType", 20 | "parameters" : [ { 21 | "kind" : "ClassValueType", 22 | "className" : "object" 23 | } ], 24 | "returnType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "" 27 | } 28 | }, 29 | "name" : "print" 30 | }, 31 | "args" : [ { 32 | "kind" : "BinaryExpr", 33 | "location" : [ 1, 7, 1, 12 ], 34 | "inferredType" : { 35 | "kind" : "ClassValueType", 36 | "className" : "int" 37 | }, 38 | "left" : { 39 | "kind" : "IntegerLiteral", 40 | "location" : [ 1, 7, 1, 8 ], 41 | "inferredType" : { 42 | "kind" : "ClassValueType", 43 | "className" : "int" 44 | }, 45 | "value" : 42 46 | }, 47 | "operator" : "%", 48 | "right" : { 49 | "kind" : "IntegerLiteral", 50 | "location" : [ 1, 12, 1, 12 ], 51 | "inferredType" : { 52 | "kind" : "ClassValueType", 53 | "className" : "int" 54 | }, 55 | "value" : 0 56 | } 57 | } ] 58 | } 59 | } ], 60 | "errors" : { 61 | "errors" : [ ], 62 | "kind" : "Errors", 63 | "location" : [ 0, 0, 0, 0 ] 64 | } 65 | } -------------------------------------------------------------------------------- /tests/typecheck/example_classes.py: -------------------------------------------------------------------------------- 1 | # A resizable list of integers 2 | class Vector(object): 3 | # Attributes 4 | items: [int] = None 5 | size: int = 0 6 | 7 | # Constructor 8 | def __init__(self:"Vector"): 9 | self.items = [0] 10 | 11 | # Returns current capacity 12 | def capacity(self:"Vector") -> int: 13 | return len(self.items) 14 | 15 | # Increases capacity of vector by one element 16 | def increase_capacity(self:"Vector") -> int: 17 | self.items = self.items + [0] 18 | return self.capacity() 19 | 20 | # Appends one item to end of vector 21 | def append(self:"Vector", item: int): 22 | if self.size == self.capacity(): 23 | self.increase_capacity() 24 | 25 | self.items[self.size] = item 26 | self.size = self.size + 1 27 | 28 | # A faster (but more memory-consuming) implementation of vector 29 | class DoublingVector(Vector): 30 | doubling_limit:int = 16 31 | 32 | # Overriding to do fewer resizes 33 | def increase_capacity(self:"DoublingVector") -> int: 34 | if (self.capacity() <= self.doubling_limit // 2): 35 | self.items = self.items + self.items 36 | else: 37 | # If doubling limit has been reached, fall back to 38 | # standard capacity increases 39 | self.items = self.items + [0] 40 | return self.capacity() 41 | 42 | vec:Vector = None 43 | num:int = 0 44 | 45 | # Create a vector and populate it with The Numbers 46 | vec = DoublingVector() 47 | for num in [4, 8, 15, 16, 23, 42]: 48 | vec.append(num) 49 | print(vec.capacity()) 50 | -------------------------------------------------------------------------------- /tests/typecheck/example_contains.py: -------------------------------------------------------------------------------- 1 | # Search in a list 2 | def contains(items:[int], x:int) -> bool: 3 | i:int = 0 4 | while i < len(items): 5 | if items[i] == x: 6 | return True 7 | i = i + 1 8 | return False 9 | 10 | if contains([4, 8, 15, 16, 23], 15): 11 | print("Item found!") # Prints this 12 | else: 13 | print("Item not found.") 14 | -------------------------------------------------------------------------------- /tests/typecheck/example_counter.py: -------------------------------------------------------------------------------- 1 | class Counter(object): 2 | n : int = 0 3 | def __init__(self : Counter): 4 | pass 5 | def inc(self : Counter): 6 | self.n = self.n + 1 7 | 8 | c : Counter = None 9 | c = Counter() 10 | c.inc() 11 | print(c.n) 12 | c.inc() 13 | print(c.n) -------------------------------------------------------------------------------- /tests/typecheck/example_exp.py: -------------------------------------------------------------------------------- 1 | # Compute x**y 2 | def exp(x: int, y: int) -> int: 3 | a: int = 0 4 | global invocations # Count calls to this function 5 | 6 | def f(i: int) -> int: 7 | nonlocal a 8 | def geta() -> int: 9 | return a 10 | if i <= 0: 11 | return geta() 12 | else: 13 | a = a * x 14 | return f(i-1) 15 | a = 1 16 | invocations = invocations + 1 17 | return f(y) 18 | 19 | invocations:int = 0 20 | print(exp(2, 10)) 21 | print(exp(3, 3)) 22 | print(invocations) -------------------------------------------------------------------------------- /tests/typecheck/example_linked_list.py: -------------------------------------------------------------------------------- 1 | class Link(object): 2 | val : int = 0 3 | next : Link = None 4 | def __init__(self : Link): 5 | pass 6 | def new(self : Link, val : int, next : Link) -> Link: 7 | self.val = val 8 | self.next = next 9 | 10 | class LinkedList(object): 11 | head : Link = None 12 | def __init(self : LinkedList): 13 | pass 14 | def is_empty(self : LinkedList) -> bool: 15 | return self.head is None 16 | def length(self : LinkedList) -> int: 17 | cur : Link = None 18 | length : int = 0 19 | cur = self.head 20 | while cur is None: 21 | length = length + 1 22 | cur = cur.next 23 | return length 24 | def add(self : LinkedList, val : int): 25 | self.head = Link().new(val, self.head) -------------------------------------------------------------------------------- /tests/typecheck/example_rat.py: -------------------------------------------------------------------------------- 1 | class Rat(object): 2 | n : int = 0 3 | d : int = 0 4 | def __init__(self : Rat): 5 | pass 6 | def new(self : Rat, n : int, d : int) -> Rat: 7 | self.n = n 8 | self.d = d 9 | return self 10 | def mul(self : Rat, other : Rat) -> Rat: 11 | return Rat().new(self.n * other.n, self.d * other.d) 12 | r1 : Rat = None 13 | r2 : Rat = None 14 | r1 = Rat().new(4, 5) 15 | r2 = Rat().new(2, 3) 16 | print(r1.mul(r2).mul(r2).n) -------------------------------------------------------------------------------- /tests/typecheck/example_tree.py: -------------------------------------------------------------------------------- 1 | # Binary-search trees 2 | class TreeNode(object): 3 | value:int = 0 4 | left:"TreeNode" = None 5 | right:"TreeNode" = None 6 | 7 | def insert(self:"TreeNode", x:int) -> bool: 8 | if x < self.value: 9 | if self.left is None: 10 | self.left = makeNode(x) 11 | return True 12 | else: 13 | return self.left.insert(x) 14 | elif x > self.value: 15 | if self.right is None: 16 | self.right = makeNode(x) 17 | return True 18 | else: 19 | return self.right.insert(x) 20 | return False 21 | 22 | def contains(self:"TreeNode", x:int) -> bool: 23 | if x < self.value: 24 | if self.left is None: 25 | return False 26 | else: 27 | return self.left.contains(x) 28 | elif x > self.value: 29 | if self.right is None: 30 | return False 31 | else: 32 | return self.right.contains(x) 33 | else: 34 | return True 35 | 36 | class Tree(object): 37 | root:TreeNode = None 38 | size:int = 0 39 | 40 | def insert(self:"Tree", x:int) -> object: 41 | if self.root is None: 42 | self.root = makeNode(x) 43 | self.size = 1 44 | else: 45 | if self.root.insert(x): 46 | self.size = self.size + 1 47 | 48 | def contains(self:"Tree", x:int) -> bool: 49 | if self.root is None: 50 | return False 51 | else: 52 | return self.root.contains(x) 53 | 54 | def makeNode(x: int) -> TreeNode: 55 | b:TreeNode = None 56 | b = TreeNode() 57 | b.value = x 58 | return b 59 | 60 | 61 | # Input parameters 62 | n:int = 100 63 | c:int = 4 64 | 65 | # Data 66 | t:Tree = None 67 | i:int = 0 68 | k:int = 37813 69 | 70 | # Crunch 71 | t = Tree() 72 | while i < n: 73 | t.insert(k) 74 | k = (k * 37813) % 37831 75 | if i % c != 0: 76 | t.insert(i) 77 | i = i + 1 78 | 79 | print(t.size) 80 | 81 | for i in [4, 8, 15, 16, 23, 42]: 82 | if t.contains(i): 83 | print(i) 84 | -------------------------------------------------------------------------------- /tests/typecheck/exp.py: -------------------------------------------------------------------------------- 1 | # Compute x**y 2 | def exp(x: int, y: int) -> int: 3 | a: int = 0 4 | def f(i: int) -> int: 5 | nonlocal a 6 | def geta() -> int: 7 | return a 8 | if i <= 0: 9 | return geta() 10 | else: 11 | a = a * x 12 | return f(i-1) 13 | a = 1 14 | return f(y) 15 | 16 | # Input parameter 17 | n:int = 42 18 | 19 | # Run [0, n] 20 | i:int = 0 21 | 22 | # Crunch 23 | while i <= n: 24 | print(exp(2, i % 31)) 25 | i = i + 1 -------------------------------------------------------------------------------- /tests/typecheck/expr_binary.py: -------------------------------------------------------------------------------- 1 | 1 + 2 * 3 > 13 // 3 % 2 or 1 != 1 and False == False 2 | 3 | -------------------------------------------------------------------------------- /tests/typecheck/expr_concat.py: -------------------------------------------------------------------------------- 1 | [1, 2] + [3, 4] 2 | "Hello " + "World" 3 | [1, 2] + [True] 4 | -------------------------------------------------------------------------------- /tests/typecheck/expr_id.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | 3 | x - 1 4 | -------------------------------------------------------------------------------- /tests/typecheck/expr_id.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 3, 6 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 9 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 9 ], 24 | "value" : 1 25 | } 26 | } ], 27 | "statements" : [ { 28 | "kind" : "ExprStmt", 29 | "location" : [ 3, 1, 3, 5 ], 30 | "expr" : { 31 | "kind" : "BinaryExpr", 32 | "location" : [ 3, 1, 3, 5 ], 33 | "left" : { 34 | "kind" : "Identifier", 35 | "location" : [ 3, 1, 3, 1 ], 36 | "name" : "x" 37 | }, 38 | "operator" : "-", 39 | "right" : { 40 | "kind" : "IntegerLiteral", 41 | "location" : [ 3, 5, 3, 5 ], 42 | "value" : 1 43 | } 44 | } 45 | } ], 46 | "errors" : { 47 | "errors" : [ ], 48 | "kind" : "Errors", 49 | "location" : [ 0, 0, 0, 0 ] 50 | } 51 | } -------------------------------------------------------------------------------- /tests/typecheck/expr_id.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 3, 6 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 9 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 9 ], 24 | "inferredType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "int" 27 | }, 28 | "value" : 1 29 | } 30 | } ], 31 | "statements" : [ { 32 | "kind" : "ExprStmt", 33 | "location" : [ 3, 1, 3, 5 ], 34 | "expr" : { 35 | "kind" : "BinaryExpr", 36 | "location" : [ 3, 1, 3, 5 ], 37 | "inferredType" : { 38 | "kind" : "ClassValueType", 39 | "className" : "int" 40 | }, 41 | "left" : { 42 | "kind" : "Identifier", 43 | "location" : [ 3, 1, 3, 1 ], 44 | "inferredType" : { 45 | "kind" : "ClassValueType", 46 | "className" : "int" 47 | }, 48 | "name" : "x" 49 | }, 50 | "operator" : "-", 51 | "right" : { 52 | "kind" : "IntegerLiteral", 53 | "location" : [ 3, 5, 3, 5 ], 54 | "inferredType" : { 55 | "kind" : "ClassValueType", 56 | "className" : "int" 57 | }, 58 | "value" : 1 59 | } 60 | } 61 | } ], 62 | "errors" : { 63 | "errors" : [ ], 64 | "kind" : "Errors", 65 | "location" : [ 0, 0, 0, 0 ] 66 | } 67 | } -------------------------------------------------------------------------------- /tests/typecheck/expr_if.py: -------------------------------------------------------------------------------- 1 | 3 if 1 > 2 else 4 2 | -------------------------------------------------------------------------------- /tests/typecheck/expr_if.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 18 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 17 ], 8 | "expr" : { 9 | "kind" : "IfExpr", 10 | "location" : [ 1, 1, 1, 17 ], 11 | "condition" : { 12 | "kind" : "BinaryExpr", 13 | "location" : [ 1, 6, 1, 10 ], 14 | "left" : { 15 | "kind" : "IntegerLiteral", 16 | "location" : [ 1, 6, 1, 6 ], 17 | "value" : 1 18 | }, 19 | "operator" : ">", 20 | "right" : { 21 | "kind" : "IntegerLiteral", 22 | "location" : [ 1, 10, 1, 10 ], 23 | "value" : 2 24 | } 25 | }, 26 | "thenExpr" : { 27 | "kind" : "IntegerLiteral", 28 | "location" : [ 1, 1, 1, 1 ], 29 | "value" : 3 30 | }, 31 | "elseExpr" : { 32 | "kind" : "IntegerLiteral", 33 | "location" : [ 1, 17, 1, 17 ], 34 | "value" : 4 35 | } 36 | } 37 | } ], 38 | "errors" : { 39 | "errors" : [ ], 40 | "kind" : "Errors", 41 | "location" : [ 0, 0, 0, 0 ] 42 | } 43 | } -------------------------------------------------------------------------------- /tests/typecheck/expr_if.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 18 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 17 ], 8 | "expr" : { 9 | "kind" : "IfExpr", 10 | "location" : [ 1, 1, 1, 17 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "int" 14 | }, 15 | "condition" : { 16 | "kind" : "BinaryExpr", 17 | "location" : [ 1, 6, 1, 10 ], 18 | "inferredType" : { 19 | "kind" : "ClassValueType", 20 | "className" : "bool" 21 | }, 22 | "left" : { 23 | "kind" : "IntegerLiteral", 24 | "location" : [ 1, 6, 1, 6 ], 25 | "inferredType" : { 26 | "kind" : "ClassValueType", 27 | "className" : "int" 28 | }, 29 | "value" : 1 30 | }, 31 | "operator" : ">", 32 | "right" : { 33 | "kind" : "IntegerLiteral", 34 | "location" : [ 1, 10, 1, 10 ], 35 | "inferredType" : { 36 | "kind" : "ClassValueType", 37 | "className" : "int" 38 | }, 39 | "value" : 2 40 | } 41 | }, 42 | "thenExpr" : { 43 | "kind" : "IntegerLiteral", 44 | "location" : [ 1, 1, 1, 1 ], 45 | "inferredType" : { 46 | "kind" : "ClassValueType", 47 | "className" : "int" 48 | }, 49 | "value" : 3 50 | }, 51 | "elseExpr" : { 52 | "kind" : "IntegerLiteral", 53 | "location" : [ 1, 17, 1, 17 ], 54 | "inferredType" : { 55 | "kind" : "ClassValueType", 56 | "className" : "int" 57 | }, 58 | "value" : 4 59 | } 60 | } 61 | } ], 62 | "errors" : { 63 | "errors" : [ ], 64 | "kind" : "Errors", 65 | "location" : [ 0, 0, 0, 0 ] 66 | } 67 | } -------------------------------------------------------------------------------- /tests/typecheck/expr_int.py: -------------------------------------------------------------------------------- 1 | 6 * 9 2 | -------------------------------------------------------------------------------- /tests/typecheck/expr_int.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 6 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 5 ], 8 | "expr" : { 9 | "kind" : "BinaryExpr", 10 | "location" : [ 1, 1, 1, 5 ], 11 | "left" : { 12 | "kind" : "IntegerLiteral", 13 | "location" : [ 1, 1, 1, 1 ], 14 | "value" : 6 15 | }, 16 | "operator" : "*", 17 | "right" : { 18 | "kind" : "IntegerLiteral", 19 | "location" : [ 1, 5, 1, 5 ], 20 | "value" : 9 21 | } 22 | } 23 | } ], 24 | "errors" : { 25 | "errors" : [ ], 26 | "kind" : "Errors", 27 | "location" : [ 0, 0, 0, 0 ] 28 | } 29 | } -------------------------------------------------------------------------------- /tests/typecheck/expr_int.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 6 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 5 ], 8 | "expr" : { 9 | "kind" : "BinaryExpr", 10 | "location" : [ 1, 1, 1, 5 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "int" 14 | }, 15 | "left" : { 16 | "kind" : "IntegerLiteral", 17 | "location" : [ 1, 1, 1, 1 ], 18 | "inferredType" : { 19 | "kind" : "ClassValueType", 20 | "className" : "int" 21 | }, 22 | "value" : 6 23 | }, 24 | "operator" : "*", 25 | "right" : { 26 | "kind" : "IntegerLiteral", 27 | "location" : [ 1, 5, 1, 5 ], 28 | "inferredType" : { 29 | "kind" : "ClassValueType", 30 | "className" : "int" 31 | }, 32 | "value" : 9 33 | } 34 | } 35 | } ], 36 | "errors" : { 37 | "errors" : [ ], 38 | "kind" : "Errors", 39 | "location" : [ 0, 0, 0, 0 ] 40 | } 41 | } -------------------------------------------------------------------------------- /tests/typecheck/expr_list_index.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | y:int = 0 3 | z:[bool] = None 4 | o:object = None 5 | 6 | x = [1, 2, 3] 7 | z = [False, True] 8 | 9 | y = x[0] 10 | x[0] = 1 11 | z[1] = z[0] 12 | o = x[1] 13 | -------------------------------------------------------------------------------- /tests/typecheck/expr_lists.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | y:[object] = None 3 | z:[bool] = None 4 | o:object = None 5 | 6 | x = [1, 2, 3] 7 | x = [] 8 | y = [1, True] 9 | z = [False, True] 10 | x = None 11 | o = x 12 | o = x = [1] 13 | -------------------------------------------------------------------------------- /tests/typecheck/expr_unary.py: -------------------------------------------------------------------------------- 1 | -1 2 | not False 3 | -------------------------------------------------------------------------------- /tests/typecheck/expr_unary.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 2, 10 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 2 ], 8 | "expr" : { 9 | "kind" : "UnaryExpr", 10 | "location" : [ 1, 1, 1, 2 ], 11 | "operator" : "-", 12 | "operand" : { 13 | "kind" : "IntegerLiteral", 14 | "location" : [ 1, 2, 1, 2 ], 15 | "value" : 1 16 | } 17 | } 18 | }, { 19 | "kind" : "ExprStmt", 20 | "location" : [ 2, 1, 2, 9 ], 21 | "expr" : { 22 | "kind" : "UnaryExpr", 23 | "location" : [ 2, 1, 2, 9 ], 24 | "operator" : "not", 25 | "operand" : { 26 | "kind" : "BooleanLiteral", 27 | "location" : [ 2, 5, 2, 9 ], 28 | "value" : false 29 | } 30 | } 31 | } ], 32 | "errors" : { 33 | "errors" : [ ], 34 | "kind" : "Errors", 35 | "location" : [ 0, 0, 0, 0 ] 36 | } 37 | } -------------------------------------------------------------------------------- /tests/typecheck/expr_unary.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 2, 10 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 2 ], 8 | "expr" : { 9 | "kind" : "UnaryExpr", 10 | "location" : [ 1, 1, 1, 2 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "int" 14 | }, 15 | "operator" : "-", 16 | "operand" : { 17 | "kind" : "IntegerLiteral", 18 | "location" : [ 1, 2, 1, 2 ], 19 | "inferredType" : { 20 | "kind" : "ClassValueType", 21 | "className" : "int" 22 | }, 23 | "value" : 1 24 | } 25 | } 26 | }, { 27 | "kind" : "ExprStmt", 28 | "location" : [ 2, 1, 2, 9 ], 29 | "expr" : { 30 | "kind" : "UnaryExpr", 31 | "location" : [ 2, 1, 2, 9 ], 32 | "inferredType" : { 33 | "kind" : "ClassValueType", 34 | "className" : "bool" 35 | }, 36 | "operator" : "not", 37 | "operand" : { 38 | "kind" : "BooleanLiteral", 39 | "location" : [ 2, 5, 2, 9 ], 40 | "inferredType" : { 41 | "kind" : "ClassValueType", 42 | "className" : "bool" 43 | }, 44 | "value" : false 45 | } 46 | } 47 | } ], 48 | "errors" : { 49 | "errors" : [ ], 50 | "kind" : "Errors", 51 | "location" : [ 0, 0, 0, 0 ] 52 | } 53 | } -------------------------------------------------------------------------------- /tests/typecheck/expr_var_assign.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | o:object = None 3 | 4 | x = o = 42 5 | -------------------------------------------------------------------------------- /tests/typecheck/expr_var_assign.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 4, 11 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 9 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 9 ], 24 | "value" : 1 25 | } 26 | }, { 27 | "kind" : "VarDef", 28 | "location" : [ 2, 1, 2, 15 ], 29 | "var" : { 30 | "kind" : "TypedVar", 31 | "location" : [ 2, 1, 2, 8 ], 32 | "identifier" : { 33 | "kind" : "Identifier", 34 | "location" : [ 2, 1, 2, 1 ], 35 | "name" : "o" 36 | }, 37 | "type" : { 38 | "kind" : "ClassType", 39 | "location" : [ 2, 3, 2, 8 ], 40 | "className" : "object" 41 | } 42 | }, 43 | "value" : { 44 | "kind" : "NoneLiteral", 45 | "location" : [ 2, 12, 2, 15 ] 46 | } 47 | } ], 48 | "statements" : [ { 49 | "kind" : "AssignStmt", 50 | "location" : [ 4, 1, 4, 10 ], 51 | "targets" : [ { 52 | "kind" : "Identifier", 53 | "location" : [ 4, 1, 4, 1 ], 54 | "name" : "x" 55 | }, { 56 | "kind" : "Identifier", 57 | "location" : [ 4, 5, 4, 5 ], 58 | "name" : "o" 59 | } ], 60 | "value" : { 61 | "kind" : "IntegerLiteral", 62 | "location" : [ 4, 9, 4, 10 ], 63 | "value" : 42 64 | } 65 | } ], 66 | "errors" : { 67 | "errors" : [ ], 68 | "kind" : "Errors", 69 | "location" : [ 0, 0, 0, 0 ] 70 | } 71 | } -------------------------------------------------------------------------------- /tests/typecheck/func_def_call.py: -------------------------------------------------------------------------------- 1 | def foo(x:str, y:bool) -> int: 2 | return bar() 3 | 4 | def bar() -> int: 5 | return 1 6 | 7 | foo("Hello", False) 8 | -------------------------------------------------------------------------------- /tests/typecheck/id_global.py: -------------------------------------------------------------------------------- 1 | x:int = 42 2 | print(x) 3 | -------------------------------------------------------------------------------- /tests/typecheck/id_global.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 2, 9 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 10 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 10 ], 24 | "inferredType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "int" 27 | }, 28 | "value" : 42 29 | } 30 | } ], 31 | "statements" : [ { 32 | "kind" : "ExprStmt", 33 | "location" : [ 2, 1, 2, 8 ], 34 | "expr" : { 35 | "kind" : "CallExpr", 36 | "location" : [ 2, 1, 2, 8 ], 37 | "inferredType" : { 38 | "kind" : "ClassValueType", 39 | "className" : "" 40 | }, 41 | "function" : { 42 | "kind" : "Identifier", 43 | "location" : [ 2, 1, 2, 5 ], 44 | "inferredType" : { 45 | "kind" : "FuncType", 46 | "parameters" : [ { 47 | "kind" : "ClassValueType", 48 | "className" : "object" 49 | } ], 50 | "returnType" : { 51 | "kind" : "ClassValueType", 52 | "className" : "" 53 | } 54 | }, 55 | "name" : "print" 56 | }, 57 | "args" : [ { 58 | "kind" : "Identifier", 59 | "location" : [ 2, 7, 2, 7 ], 60 | "inferredType" : { 61 | "kind" : "ClassValueType", 62 | "className" : "int" 63 | }, 64 | "name" : "x" 65 | } ] 66 | } 67 | } ], 68 | "errors" : { 69 | "errors" : [ ], 70 | "kind" : "Errors", 71 | "location" : [ 0, 0, 0, 0 ] 72 | } 73 | } -------------------------------------------------------------------------------- /tests/typecheck/id_local.py: -------------------------------------------------------------------------------- 1 | def f() -> int: 2 | x:int = 1 3 | return x 4 | 5 | print(f()) 6 | -------------------------------------------------------------------------------- /tests/typecheck/len_invalid_1.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | print(len(x)) 4 | -------------------------------------------------------------------------------- /tests/typecheck/len_invalid_2.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | 3 | print(len(x)) 4 | -------------------------------------------------------------------------------- /tests/typecheck/list_concat.py: -------------------------------------------------------------------------------- 1 | def concat(x:[int], y:[int]) -> [int]: 2 | return x + y 3 | 4 | z:[int] = None 5 | i:int = 0 6 | 7 | z = concat([1,2,3], [4,5,6]) 8 | 9 | while i < len(z): 10 | print(z[i]) 11 | i = i + 1 12 | 13 | -------------------------------------------------------------------------------- /tests/typecheck/list_concat_2.py: -------------------------------------------------------------------------------- 1 | z:[int] = None 2 | i:int = 0 3 | 4 | z = [1,2,3] + [4,5,6] + [7,8,9] 5 | 6 | while i < len(z): 7 | print(z[i]) 8 | i = i + 1 9 | -------------------------------------------------------------------------------- /tests/typecheck/list_concat_none.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | y:[int] = None 3 | 4 | print(len(x+y)) 5 | -------------------------------------------------------------------------------- /tests/typecheck/list_get_element.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [1, 2, 3] 4 | print(x[0]) 5 | print(x[1]) 6 | print(x[2]) 7 | -------------------------------------------------------------------------------- /tests/typecheck/list_get_element_complex.py: -------------------------------------------------------------------------------- 1 | next:int = 0 2 | 3 | def next_int() -> int: 4 | global next 5 | next = next + 1 6 | return next 7 | 8 | def make_list() -> [int]: 9 | return [next_int(), next_int(), next_int()] 10 | 11 | print(make_list()[next_int() - 3]) 12 | -------------------------------------------------------------------------------- /tests/typecheck/list_get_element_none.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | print(x[0]) 4 | -------------------------------------------------------------------------------- /tests/typecheck/list_get_element_oob_1.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [1, 2, 3] 4 | print(x[-1]) 5 | -------------------------------------------------------------------------------- /tests/typecheck/list_get_element_oob_2.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [1, 2, 3] 4 | print(x[3]) 5 | -------------------------------------------------------------------------------- /tests/typecheck/list_get_element_oob_3.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [] 4 | print(x[0]) 5 | -------------------------------------------------------------------------------- /tests/typecheck/list_len.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [1, 2, 3] 4 | print(len(x)) 5 | -------------------------------------------------------------------------------- /tests/typecheck/list_len_empty.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [] 4 | print(len(x)) 5 | -------------------------------------------------------------------------------- /tests/typecheck/list_set_element.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [1, 2, 3] 4 | x[0] = 4 5 | x[1] = 5 6 | x[2] = 6 7 | print(x[0]) 8 | print(x[1]) 9 | print(x[2]) 10 | -------------------------------------------------------------------------------- /tests/typecheck/list_set_element_none.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x[0] = 1 4 | 5 | -------------------------------------------------------------------------------- /tests/typecheck/list_set_element_none.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 3, 9 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 14 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 7 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ListType", 17 | "location" : [ 1, 3, 1, 7 ], 18 | "elementType" : { 19 | "kind" : "ClassType", 20 | "location" : [ 1, 4, 1, 6 ], 21 | "className" : "int" 22 | } 23 | } 24 | }, 25 | "value" : { 26 | "kind" : "NoneLiteral", 27 | "location" : [ 1, 11, 1, 14 ], 28 | "inferredType" : { 29 | "kind" : "ClassValueType", 30 | "className" : "" 31 | } 32 | } 33 | } ], 34 | "statements" : [ { 35 | "kind" : "AssignStmt", 36 | "location" : [ 3, 1, 3, 8 ], 37 | "targets" : [ { 38 | "kind" : "IndexExpr", 39 | "location" : [ 3, 1, 3, 4 ], 40 | "inferredType" : { 41 | "kind" : "ClassValueType", 42 | "className" : "int" 43 | }, 44 | "list" : { 45 | "kind" : "Identifier", 46 | "location" : [ 3, 1, 3, 1 ], 47 | "inferredType" : { 48 | "kind" : "ListValueType", 49 | "elementType" : { 50 | "kind" : "ClassValueType", 51 | "className" : "int" 52 | } 53 | }, 54 | "name" : "x" 55 | }, 56 | "index" : { 57 | "kind" : "IntegerLiteral", 58 | "location" : [ 3, 3, 3, 3 ], 59 | "inferredType" : { 60 | "kind" : "ClassValueType", 61 | "className" : "int" 62 | }, 63 | "value" : 0 64 | } 65 | } ], 66 | "value" : { 67 | "kind" : "IntegerLiteral", 68 | "location" : [ 3, 8, 3, 8 ], 69 | "inferredType" : { 70 | "kind" : "ClassValueType", 71 | "className" : "int" 72 | }, 73 | "value" : 1 74 | } 75 | } ], 76 | "errors" : { 77 | "errors" : [ ], 78 | "kind" : "Errors", 79 | "location" : [ 0, 0, 0, 0 ] 80 | } 81 | } -------------------------------------------------------------------------------- /tests/typecheck/list_set_element_oob_1.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [1, 2, 3] 4 | x[-1] = 4 5 | print(x[0]) 6 | print(x[1]) 7 | print(x[2]) 8 | -------------------------------------------------------------------------------- /tests/typecheck/list_set_element_oob_2.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [1, 2, 3] 4 | x[4] = 4 5 | print(x[0]) 6 | print(x[1]) 7 | print(x[2]) 8 | -------------------------------------------------------------------------------- /tests/typecheck/list_set_element_oob_3.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | 3 | x = [] 4 | x[0] = 4 5 | -------------------------------------------------------------------------------- /tests/typecheck/literal_bool.py: -------------------------------------------------------------------------------- 1 | print(True) 2 | print(False) 3 | -------------------------------------------------------------------------------- /tests/typecheck/literal_int.py: -------------------------------------------------------------------------------- 1 | print(42) 2 | print(65999) 3 | -------------------------------------------------------------------------------- /tests/typecheck/literal_str.py: -------------------------------------------------------------------------------- 1 | print("Hello World") 2 | -------------------------------------------------------------------------------- /tests/typecheck/literal_str.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 21 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 20 ], 8 | "expr" : { 9 | "kind" : "CallExpr", 10 | "location" : [ 1, 1, 1, 20 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "" 14 | }, 15 | "function" : { 16 | "kind" : "Identifier", 17 | "location" : [ 1, 1, 1, 5 ], 18 | "inferredType" : { 19 | "kind" : "FuncType", 20 | "parameters" : [ { 21 | "kind" : "ClassValueType", 22 | "className" : "object" 23 | } ], 24 | "returnType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "" 27 | } 28 | }, 29 | "name" : "print" 30 | }, 31 | "args" : [ { 32 | "kind" : "StringLiteral", 33 | "location" : [ 1, 7, 1, 19 ], 34 | "inferredType" : { 35 | "kind" : "ClassValueType", 36 | "className" : "str" 37 | }, 38 | "value" : "Hello World" 39 | } ] 40 | } 41 | } ], 42 | "errors" : { 43 | "errors" : [ ], 44 | "kind" : "Errors", 45 | "location" : [ 0, 0, 0, 0 ] 46 | } 47 | } -------------------------------------------------------------------------------- /tests/typecheck/nested.py: -------------------------------------------------------------------------------- 1 | g: int = 1 2 | def foo(x: int) -> int: 3 | y: int = 2 4 | def bar() -> int: 5 | z: int = 3 6 | def baz() -> int: 7 | return y 8 | return baz() 9 | return bar() 10 | 11 | print(foo(g)) 12 | -------------------------------------------------------------------------------- /tests/typecheck/nested2.py: -------------------------------------------------------------------------------- 1 | g: int = 1 2 | def foo(x: int) -> int: 3 | y: int = 2 4 | def bar() -> int: 5 | z: int = 3 6 | def baz() -> int: 7 | return qux(y) 8 | return baz() 9 | def qux(p: int) -> int: 10 | return p 11 | 12 | return bar() 13 | 14 | print(foo(g)) 15 | -------------------------------------------------------------------------------- /tests/typecheck/object_attr_get.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | class B(A): 5 | b:bool = True 6 | 7 | def __init__(self:"B"): 8 | print("B") 9 | 10 | a:A = None 11 | b:B = None 12 | 13 | a = b = B() 14 | print(a.a) 15 | print(b.a) 16 | print(b.b) 17 | -------------------------------------------------------------------------------- /tests/typecheck/object_attr_get_none.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | class B(A): 5 | b:bool = True 6 | 7 | def __init__(self:"B"): 8 | print("B") 9 | 10 | a:A = None 11 | b:B = None 12 | 13 | a = B() 14 | print(a.a) 15 | print(b.a) 16 | print(b.b) 17 | -------------------------------------------------------------------------------- /tests/typecheck/object_attr_set.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | class B(A): 5 | b:bool = True 6 | 7 | def __init__(self:"B"): 8 | print("B") 9 | 10 | a:A = None 11 | b:B = None 12 | 13 | a = b = B() 14 | b.a = 1 15 | b.b = False 16 | print(a.a) 17 | print(b.a) 18 | print(b.b) 19 | -------------------------------------------------------------------------------- /tests/typecheck/object_attr_set_eval_order.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | class B(A): 5 | b:bool = True 6 | 7 | def __init__(self:"B"): 8 | print("B") 9 | 10 | a:A = None 11 | b:B = None 12 | 13 | def get_b() -> B: 14 | print("Getting B") 15 | return b 16 | 17 | def get_one() -> int: 18 | print("Getting 1") 19 | return 1 20 | 21 | def get_false() -> bool: 22 | print("Getting False") 23 | return False 24 | 25 | a = b = B() 26 | get_b().a = get_one() 27 | print("Assigned B.a") 28 | get_b().b = get_false() 29 | print("Assigned B.b") 30 | 31 | print(a.a) 32 | print(b.a) 33 | print(b.b) 34 | -------------------------------------------------------------------------------- /tests/typecheck/object_attr_set_none.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | class B(A): 5 | b:bool = True 6 | 7 | def __init__(self:"B"): 8 | print("B") 9 | 10 | a:A = None 11 | b:B = None 12 | 13 | a = B() 14 | print(a.a) 15 | 16 | b.a = 1 17 | b.b = False 18 | print(b.a) 19 | print(b.b) 20 | -------------------------------------------------------------------------------- /tests/typecheck/object_init.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | class B(A): 5 | b:bool = True 6 | 7 | def __init__(self:"B"): 8 | print("B") 9 | 10 | 11 | B() 12 | -------------------------------------------------------------------------------- /tests/typecheck/object_method.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | def foo(self:"A", ignore:object) -> int: 5 | return self.a 6 | 7 | class B(A): 8 | b:bool = True 9 | 10 | def __init__(self:"B"): 11 | print("B") 12 | 13 | def bar(self:"B") -> int: 14 | return self.foo(self.b) 15 | 16 | print(B().bar()) 17 | -------------------------------------------------------------------------------- /tests/typecheck/object_method_complex_call.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | def foo(self:"A", ignore:object) -> int: 5 | return self.a 6 | 7 | class B(A): 8 | b:bool = True 9 | 10 | def __init__(self:"B"): 11 | print("B") 12 | 13 | def bar(self:"B") -> int: 14 | return self.foo(self.foo(print("..."))) 15 | 16 | def foo(self:"B", ignore:object) -> int: 17 | return 1 18 | 19 | print(B().bar()) 20 | -------------------------------------------------------------------------------- /tests/typecheck/object_method_nested.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | def foo(self:"A", ignore:object) -> int: 5 | return self.a 6 | 7 | class B(A): 8 | b:bool = True 9 | 10 | def __init__(self:"B"): 11 | print("B") 12 | 13 | def bar(self:"B") -> int: 14 | def qux(p: bool) -> int: 15 | return self.foo(p) 16 | return qux(True) 17 | 18 | print(B().bar()) 19 | -------------------------------------------------------------------------------- /tests/typecheck/object_method_none.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | def foo(self:"A", ignore:object) -> int: 5 | return self.a 6 | 7 | class B(A): 8 | b:bool = True 9 | 10 | def __init__(self:"B"): 11 | print("B") 12 | 13 | def bar(self:"B") -> int: 14 | a:A = None 15 | return a.foo(self.b) 16 | 17 | print(B().bar()) 18 | -------------------------------------------------------------------------------- /tests/typecheck/object_method_override.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | def foo(self:"A", ignore:object) -> int: 5 | return self.a 6 | 7 | class B(A): 8 | b:bool = True 9 | 10 | def __init__(self:"B"): 11 | print("B") 12 | 13 | def bar(self:"B") -> int: 14 | return self.foo(self.b) 15 | 16 | def foo(self:"B", ignore:object) -> int: 17 | return 1 18 | 19 | print(B().bar()) 20 | -------------------------------------------------------------------------------- /tests/typecheck/op_add.py: -------------------------------------------------------------------------------- 1 | print(1 + 100) 2 | -------------------------------------------------------------------------------- /tests/typecheck/op_add.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 15 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 14 ], 8 | "expr" : { 9 | "kind" : "CallExpr", 10 | "location" : [ 1, 1, 1, 14 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "" 14 | }, 15 | "function" : { 16 | "kind" : "Identifier", 17 | "location" : [ 1, 1, 1, 5 ], 18 | "inferredType" : { 19 | "kind" : "FuncType", 20 | "parameters" : [ { 21 | "kind" : "ClassValueType", 22 | "className" : "object" 23 | } ], 24 | "returnType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "" 27 | } 28 | }, 29 | "name" : "print" 30 | }, 31 | "args" : [ { 32 | "kind" : "BinaryExpr", 33 | "location" : [ 1, 7, 1, 13 ], 34 | "inferredType" : { 35 | "kind" : "ClassValueType", 36 | "className" : "int" 37 | }, 38 | "left" : { 39 | "kind" : "IntegerLiteral", 40 | "location" : [ 1, 7, 1, 7 ], 41 | "inferredType" : { 42 | "kind" : "ClassValueType", 43 | "className" : "int" 44 | }, 45 | "value" : 1 46 | }, 47 | "operator" : "+", 48 | "right" : { 49 | "kind" : "IntegerLiteral", 50 | "location" : [ 1, 11, 1, 13 ], 51 | "inferredType" : { 52 | "kind" : "ClassValueType", 53 | "className" : "int" 54 | }, 55 | "value" : 100 56 | } 57 | } ] 58 | } 59 | } ], 60 | "errors" : { 61 | "errors" : [ ], 62 | "kind" : "Errors", 63 | "location" : [ 0, 0, 0, 0 ] 64 | } 65 | } -------------------------------------------------------------------------------- /tests/typecheck/op_cmp_bool.py: -------------------------------------------------------------------------------- 1 | print(True == True) 2 | print(True == False) 3 | print(False == True) 4 | print(False == False) 5 | print(True != True) 6 | print(True != False) 7 | print(False != True) 8 | print(False != False) 9 | -------------------------------------------------------------------------------- /tests/typecheck/op_cmp_int.py: -------------------------------------------------------------------------------- 1 | x:int = 42 2 | y:int = 7 3 | 4 | print(x == y) 5 | print(x != y) 6 | print(x < y) 7 | print(x <= y) 8 | print(x > y) 9 | print(x >= y) 10 | 11 | print(x == x) 12 | print(x != x) 13 | print(x < x) 14 | print(x <= x) 15 | print(x > x) 16 | print(x >= x) 17 | -------------------------------------------------------------------------------- /tests/typecheck/op_div_mod.py: -------------------------------------------------------------------------------- 1 | x:int = 42 2 | y:int = 9 3 | 4 | print(x // y) 5 | print(x % y) 6 | -------------------------------------------------------------------------------- /tests/typecheck/op_is.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | a:int = 42 3 | 4 | a1:A = None 5 | a2:A = None 6 | a3:A = None 7 | a4:A = None 8 | 9 | a1 = A() 10 | a2 = a1 11 | a3 = A() 12 | 13 | print(a1 is a1) 14 | print(a1 is a2) 15 | print(a1 is a3) 16 | print(a1 is a4) 17 | print(a1 is None) 18 | print(a4 is None) 19 | print(None is None) 20 | -------------------------------------------------------------------------------- /tests/typecheck/op_logical.py: -------------------------------------------------------------------------------- 1 | def f() -> bool: 2 | print("f called") 3 | return True 4 | 5 | def g() -> bool: 6 | print("g called") 7 | return False 8 | 9 | if f() or g(): # Short-circuit 10 | if g() and f(): # Short-circuit 11 | print("Never") 12 | else: 13 | print(not (f() and (g() or f()))) 14 | -------------------------------------------------------------------------------- /tests/typecheck/op_mul.py: -------------------------------------------------------------------------------- 1 | print(6*9*2) 2 | -------------------------------------------------------------------------------- /tests/typecheck/op_negate.py: -------------------------------------------------------------------------------- 1 | x:int = 42 2 | print(-x) 3 | -------------------------------------------------------------------------------- /tests/typecheck/op_negate.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 2, 10 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 10 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 10 ], 24 | "inferredType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "int" 27 | }, 28 | "value" : 42 29 | } 30 | } ], 31 | "statements" : [ { 32 | "kind" : "ExprStmt", 33 | "location" : [ 2, 1, 2, 9 ], 34 | "expr" : { 35 | "kind" : "CallExpr", 36 | "location" : [ 2, 1, 2, 9 ], 37 | "inferredType" : { 38 | "kind" : "ClassValueType", 39 | "className" : "" 40 | }, 41 | "function" : { 42 | "kind" : "Identifier", 43 | "location" : [ 2, 1, 2, 5 ], 44 | "inferredType" : { 45 | "kind" : "FuncType", 46 | "parameters" : [ { 47 | "kind" : "ClassValueType", 48 | "className" : "object" 49 | } ], 50 | "returnType" : { 51 | "kind" : "ClassValueType", 52 | "className" : "" 53 | } 54 | }, 55 | "name" : "print" 56 | }, 57 | "args" : [ { 58 | "kind" : "UnaryExpr", 59 | "location" : [ 2, 7, 2, 8 ], 60 | "inferredType" : { 61 | "kind" : "ClassValueType", 62 | "className" : "int" 63 | }, 64 | "operator" : "-", 65 | "operand" : { 66 | "kind" : "Identifier", 67 | "location" : [ 2, 8, 2, 8 ], 68 | "inferredType" : { 69 | "kind" : "ClassValueType", 70 | "className" : "int" 71 | }, 72 | "name" : "x" 73 | } 74 | } ] 75 | } 76 | } ], 77 | "errors" : { 78 | "errors" : [ ], 79 | "kind" : "Errors", 80 | "location" : [ 0, 0, 0, 0 ] 81 | } 82 | } -------------------------------------------------------------------------------- /tests/typecheck/op_sub.py: -------------------------------------------------------------------------------- 1 | print(1 - 100) 2 | -------------------------------------------------------------------------------- /tests/typecheck/op_sub.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 15 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 14 ], 8 | "expr" : { 9 | "kind" : "CallExpr", 10 | "location" : [ 1, 1, 1, 14 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "" 14 | }, 15 | "function" : { 16 | "kind" : "Identifier", 17 | "location" : [ 1, 1, 1, 5 ], 18 | "inferredType" : { 19 | "kind" : "FuncType", 20 | "parameters" : [ { 21 | "kind" : "ClassValueType", 22 | "className" : "object" 23 | } ], 24 | "returnType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "" 27 | } 28 | }, 29 | "name" : "print" 30 | }, 31 | "args" : [ { 32 | "kind" : "BinaryExpr", 33 | "location" : [ 1, 7, 1, 13 ], 34 | "inferredType" : { 35 | "kind" : "ClassValueType", 36 | "className" : "int" 37 | }, 38 | "left" : { 39 | "kind" : "IntegerLiteral", 40 | "location" : [ 1, 7, 1, 7 ], 41 | "inferredType" : { 42 | "kind" : "ClassValueType", 43 | "className" : "int" 44 | }, 45 | "value" : 1 46 | }, 47 | "operator" : "-", 48 | "right" : { 49 | "kind" : "IntegerLiteral", 50 | "location" : [ 1, 11, 1, 13 ], 51 | "inferredType" : { 52 | "kind" : "ClassValueType", 53 | "className" : "int" 54 | }, 55 | "value" : 100 56 | } 57 | } ] 58 | } 59 | } ], 60 | "errors" : { 61 | "errors" : [ ], 62 | "kind" : "Errors", 63 | "location" : [ 0, 0, 0, 0 ] 64 | } 65 | } -------------------------------------------------------------------------------- /tests/typecheck/pass.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /tests/typecheck/pass.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 5 ], 4 | "declarations" : [ ], 5 | "statements" : [ ], 6 | "errors" : { 7 | "errors" : [ ], 8 | "kind" : "Errors", 9 | "location" : [ 0, 0, 0, 0 ] 10 | } 11 | } -------------------------------------------------------------------------------- /tests/typecheck/predef_constructors.py: -------------------------------------------------------------------------------- 1 | print(object() is None) 2 | print(int()) 3 | print(str()) 4 | print(bool()) 5 | -------------------------------------------------------------------------------- /tests/typecheck/prime.py: -------------------------------------------------------------------------------- 1 | # Get the n-th prime starting from 2 2 | def get_prime(n:int) -> int: 3 | candidate:int = 2 4 | found:int = 0 5 | while True: 6 | if is_prime(candidate): 7 | found = found + 1 8 | if found == n: 9 | return candidate 10 | candidate = candidate + 1 11 | return 0 # Never happens 12 | 13 | def is_prime(x:int) -> bool: 14 | div:int = 2 15 | while div < x: 16 | if x % div == 0: 17 | return False 18 | div = div + 1 19 | return True 20 | 21 | # Input parameter 22 | n:int = 15 23 | 24 | # Run [1, n] 25 | i:int = 1 26 | 27 | # Crunch 28 | while i <= n: 29 | print(get_prime(i)) 30 | i = i + 1 31 | -------------------------------------------------------------------------------- /tests/typecheck/stdlib.py: -------------------------------------------------------------------------------- 1 | # ChocoPy library functions 2 | def int_to_str(x: int) -> str: 3 | digits:[str] = None 4 | result:str = "" 5 | 6 | # Set-up digit mapping 7 | digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] 8 | 9 | # Write sign if necessary 10 | if x < 0: 11 | result = "-" 12 | x = -x 13 | 14 | # Write digits using a recursive call 15 | if x >= 10: 16 | result = result + int_to_str(x // 10) 17 | result = result + digits[x % 10] 18 | return result 19 | 20 | def str_to_int(x: str) -> int: 21 | result:int = 0 22 | digit:int = 0 23 | char:str = "" 24 | sign:int = 1 25 | first_char:bool = True 26 | 27 | # Parse digits 28 | for char in x: 29 | if char == "-": 30 | if not first_char: 31 | return 0 # Error 32 | sign = -1 33 | elif char == "0": 34 | digit = 0 35 | elif char == "1": 36 | digit = 1 37 | elif char == "2": 38 | digit = 2 39 | elif char == "3": 40 | digit = 3 41 | elif char == "3": 42 | digit = 3 43 | elif char == "4": 44 | digit = 4 45 | elif char == "5": 46 | digit = 5 47 | elif char == "6": 48 | digit = 6 49 | elif char == "7": 50 | digit = 7 51 | elif char == "8": 52 | digit = 8 53 | elif char == "9": 54 | digit = 9 55 | else: 56 | return 0 # On error 57 | first_char = False 58 | result = result * 10 + digit 59 | 60 | # Compute result 61 | return result * sign 62 | 63 | # Input parameters 64 | c:int = 42 65 | n:int = 10 66 | 67 | # Run [-nc, nc] with step size c 68 | s:str = "" 69 | i:int = 0 70 | i = -n * c 71 | 72 | # Crunch 73 | while i <= n * c: 74 | s = int_to_str(i) 75 | print(s) 76 | i = str_to_int(s) + c 77 | 78 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_list.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | z:[int] = None 3 | 4 | z = [1, 2, 3] 5 | 6 | for x in z: 7 | print(x) 8 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_list_empty.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | y:int = 0 3 | z:[int] = None 4 | e:[int] = None 5 | 6 | z = [1,2,3] 7 | e = [] 8 | 9 | for x in z: 10 | for y in e: 11 | print("Never") 12 | print(x) 13 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_list_eval.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | z:[int] = None 3 | 4 | z = [1, 2, 3] 5 | 6 | for x in z: 7 | z = [] 8 | print(x) 9 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_list_modify.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | z:[int] = None 3 | 4 | z = [1, 2, 1] 5 | 6 | for x in z: 7 | z[x] = x 8 | print(x) 9 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_list_nested.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | y:int = 0 3 | z:[int] = None 4 | 5 | z = [1, 2, 3] 6 | 7 | for x in z: 8 | for y in z: 9 | print(x * y) 10 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_list_nested_same_var.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | y:int = 0 3 | z:[int] = None 4 | 5 | z = [1, 2, 3] 6 | 7 | for x in z: 8 | for x in z: 9 | print(x) 10 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_list_none.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | z:[int] = None 3 | 4 | for x in z: 5 | print(x) 6 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_list_nonlocal.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | def crunch(zz:[[int]]) -> object: 3 | z:[int] = None 4 | global x 5 | def make_z() -> object: 6 | nonlocal z 7 | for z in zz: 8 | pass # Set z to last element in zz 9 | 10 | make_z() 11 | for x in z: 12 | pass # Set x to last element in z 13 | 14 | crunch([[1,2],[2,3],[4,5],[6,7]]) 15 | print(x) 16 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_list_return.py: -------------------------------------------------------------------------------- 1 | def print_list(z:[int]) -> object: 2 | x:int = 0 3 | for x in z: 4 | print(x) 5 | if x >= 30: 6 | return 7 | 8 | print_list([10,20,30,40]) 9 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_lists.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | 3 | for x in [1, 2, 3]: 4 | x + 1 5 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_lists.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 5, 1 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 9 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 9 ], 24 | "value" : 0 25 | } 26 | } ], 27 | "statements" : [ { 28 | "kind" : "ForStmt", 29 | "location" : [ 3, 1, 5, 1 ], 30 | "identifier" : { 31 | "kind" : "Identifier", 32 | "location" : [ 3, 5, 3, 5 ], 33 | "name" : "x" 34 | }, 35 | "iterable" : { 36 | "kind" : "ListExpr", 37 | "location" : [ 3, 10, 3, 18 ], 38 | "elements" : [ { 39 | "kind" : "IntegerLiteral", 40 | "location" : [ 3, 11, 3, 11 ], 41 | "value" : 1 42 | }, { 43 | "kind" : "IntegerLiteral", 44 | "location" : [ 3, 14, 3, 14 ], 45 | "value" : 2 46 | }, { 47 | "kind" : "IntegerLiteral", 48 | "location" : [ 3, 17, 3, 17 ], 49 | "value" : 3 50 | } ] 51 | }, 52 | "body" : [ { 53 | "kind" : "ExprStmt", 54 | "location" : [ 4, 5, 4, 9 ], 55 | "expr" : { 56 | "kind" : "BinaryExpr", 57 | "location" : [ 4, 5, 4, 9 ], 58 | "left" : { 59 | "kind" : "Identifier", 60 | "location" : [ 4, 5, 4, 5 ], 61 | "name" : "x" 62 | }, 63 | "operator" : "+", 64 | "right" : { 65 | "kind" : "IntegerLiteral", 66 | "location" : [ 4, 9, 4, 9 ], 67 | "value" : 1 68 | } 69 | } 70 | } ] 71 | } ], 72 | "errors" : { 73 | "errors" : [ ], 74 | "kind" : "Errors", 75 | "location" : [ 0, 0, 0, 0 ] 76 | } 77 | } -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_str.py: -------------------------------------------------------------------------------- 1 | x:str = "" 2 | z:str = "abc" 3 | 4 | for x in z: 5 | print(x) 6 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_str_empty.py: -------------------------------------------------------------------------------- 1 | x:str = "" 2 | y:str = "123" 3 | z:str = "abc" 4 | 5 | for x in z: 6 | print(x) 7 | for x in "": 8 | print(x) 9 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_str_eval.py: -------------------------------------------------------------------------------- 1 | x:str = "" 2 | z:str = "abc" 3 | 4 | for x in z: 5 | z = "doesn't matter" 6 | print(x) 7 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_str_nested.py: -------------------------------------------------------------------------------- 1 | x:str = "" 2 | y:str = "123" 3 | z:str = "abc" 4 | 5 | for x in z: 6 | print(x) 7 | for x in y: 8 | print(x) 9 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_str_same_var.py: -------------------------------------------------------------------------------- 1 | x:str = "xXx" 2 | 3 | for x in x: 4 | print(x) 5 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_strings.py: -------------------------------------------------------------------------------- 1 | s:str = "Hello" 2 | 3 | for s in s: 4 | s[0] 5 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_for_strings.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 5, 1 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 15 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "s" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "str" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "StringLiteral", 23 | "location" : [ 1, 9, 1, 15 ], 24 | "value" : "Hello" 25 | } 26 | } ], 27 | "statements" : [ { 28 | "kind" : "ForStmt", 29 | "location" : [ 3, 1, 5, 1 ], 30 | "identifier" : { 31 | "kind" : "Identifier", 32 | "location" : [ 3, 5, 3, 5 ], 33 | "name" : "s" 34 | }, 35 | "iterable" : { 36 | "kind" : "Identifier", 37 | "location" : [ 3, 10, 3, 10 ], 38 | "name" : "s" 39 | }, 40 | "body" : [ { 41 | "kind" : "ExprStmt", 42 | "location" : [ 4, 5, 4, 8 ], 43 | "expr" : { 44 | "kind" : "IndexExpr", 45 | "location" : [ 4, 5, 4, 8 ], 46 | "list" : { 47 | "kind" : "Identifier", 48 | "location" : [ 4, 5, 4, 5 ], 49 | "name" : "s" 50 | }, 51 | "index" : { 52 | "kind" : "IntegerLiteral", 53 | "location" : [ 4, 7, 4, 7 ], 54 | "value" : 0 55 | } 56 | } 57 | } ] 58 | } ], 59 | "errors" : { 60 | "errors" : [ ], 61 | "kind" : "Errors", 62 | "location" : [ 0, 0, 0, 0 ] 63 | } 64 | } -------------------------------------------------------------------------------- /tests/typecheck/stmt_if.py: -------------------------------------------------------------------------------- 1 | if False: 2 | pass 3 | elif True: 4 | if 1 == 1: 5 | pass 6 | else: 7 | pass 8 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_if.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 8, 1 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "IfStmt", 7 | "location" : [ 1, 1, 8, 1 ], 8 | "condition" : { 9 | "kind" : "BooleanLiteral", 10 | "location" : [ 1, 4, 1, 8 ], 11 | "value" : false 12 | }, 13 | "thenBody" : [ ], 14 | "elseBody" : [ { 15 | "kind" : "IfStmt", 16 | "location" : [ 3, 1, 8, 1 ], 17 | "condition" : { 18 | "kind" : "BooleanLiteral", 19 | "location" : [ 3, 6, 3, 9 ], 20 | "value" : true 21 | }, 22 | "thenBody" : [ { 23 | "kind" : "IfStmt", 24 | "location" : [ 4, 5, 6, 0 ], 25 | "condition" : { 26 | "kind" : "BinaryExpr", 27 | "location" : [ 4, 8, 4, 13 ], 28 | "left" : { 29 | "kind" : "IntegerLiteral", 30 | "location" : [ 4, 8, 4, 8 ], 31 | "value" : 1 32 | }, 33 | "operator" : "==", 34 | "right" : { 35 | "kind" : "IntegerLiteral", 36 | "location" : [ 4, 13, 4, 13 ], 37 | "value" : 1 38 | } 39 | }, 40 | "thenBody" : [ ], 41 | "elseBody" : [ ] 42 | } ], 43 | "elseBody" : [ ] 44 | } ] 45 | } ], 46 | "errors" : { 47 | "errors" : [ ], 48 | "kind" : "Errors", 49 | "location" : [ 0, 0, 0, 0 ] 50 | } 51 | } -------------------------------------------------------------------------------- /tests/typecheck/stmt_if.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 8, 1 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "IfStmt", 7 | "location" : [ 1, 1, 8, 1 ], 8 | "condition" : { 9 | "kind" : "BooleanLiteral", 10 | "location" : [ 1, 4, 1, 8 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "bool" 14 | }, 15 | "value" : false 16 | }, 17 | "thenBody" : [ ], 18 | "elseBody" : [ { 19 | "kind" : "IfStmt", 20 | "location" : [ 3, 1, 8, 1 ], 21 | "condition" : { 22 | "kind" : "BooleanLiteral", 23 | "location" : [ 3, 6, 3, 9 ], 24 | "inferredType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "bool" 27 | }, 28 | "value" : true 29 | }, 30 | "thenBody" : [ { 31 | "kind" : "IfStmt", 32 | "location" : [ 4, 5, 6, 0 ], 33 | "condition" : { 34 | "kind" : "BinaryExpr", 35 | "location" : [ 4, 8, 4, 13 ], 36 | "inferredType" : { 37 | "kind" : "ClassValueType", 38 | "className" : "bool" 39 | }, 40 | "left" : { 41 | "kind" : "IntegerLiteral", 42 | "location" : [ 4, 8, 4, 8 ], 43 | "inferredType" : { 44 | "kind" : "ClassValueType", 45 | "className" : "int" 46 | }, 47 | "value" : 1 48 | }, 49 | "operator" : "==", 50 | "right" : { 51 | "kind" : "IntegerLiteral", 52 | "location" : [ 4, 13, 4, 13 ], 53 | "inferredType" : { 54 | "kind" : "ClassValueType", 55 | "className" : "int" 56 | }, 57 | "value" : 1 58 | } 59 | }, 60 | "thenBody" : [ ], 61 | "elseBody" : [ ] 62 | } ], 63 | "elseBody" : [ ] 64 | } ] 65 | } ], 66 | "errors" : { 67 | "errors" : [ ], 68 | "kind" : "Errors", 69 | "location" : [ 0, 0, 0, 0 ] 70 | } 71 | } -------------------------------------------------------------------------------- /tests/typecheck/stmt_list_assign.py: -------------------------------------------------------------------------------- 1 | x:[int] = None 2 | y:[object] = None 3 | 4 | x = [1, 2] 5 | y = [None] 6 | x[0] = 3 7 | x[1] = y[0] = 4 8 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_return_early.py: -------------------------------------------------------------------------------- 1 | def f() -> int: 2 | while True: 3 | return 1 4 | return 0 5 | 6 | print(f()) 7 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_var_assign.py: -------------------------------------------------------------------------------- 1 | x:int = 1 2 | y:bool = True 3 | z:str = "" 4 | o:object = None 5 | 6 | x = 2 7 | y = False 8 | z = "Hello" 9 | o = z 10 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_while.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | while x < 100: 3 | x = x + 1 4 | -------------------------------------------------------------------------------- /tests/typecheck/stmt_while.py.ast: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 4, 1 ], 4 | "declarations" : [ { 5 | "kind" : "VarDef", 6 | "location" : [ 1, 1, 1, 9 ], 7 | "var" : { 8 | "kind" : "TypedVar", 9 | "location" : [ 1, 1, 1, 5 ], 10 | "identifier" : { 11 | "kind" : "Identifier", 12 | "location" : [ 1, 1, 1, 1 ], 13 | "name" : "x" 14 | }, 15 | "type" : { 16 | "kind" : "ClassType", 17 | "location" : [ 1, 3, 1, 5 ], 18 | "className" : "int" 19 | } 20 | }, 21 | "value" : { 22 | "kind" : "IntegerLiteral", 23 | "location" : [ 1, 9, 1, 9 ], 24 | "value" : 0 25 | } 26 | } ], 27 | "statements" : [ { 28 | "kind" : "WhileStmt", 29 | "location" : [ 2, 1, 4, 1 ], 30 | "condition" : { 31 | "kind" : "BinaryExpr", 32 | "location" : [ 2, 7, 2, 13 ], 33 | "left" : { 34 | "kind" : "Identifier", 35 | "location" : [ 2, 7, 2, 7 ], 36 | "name" : "x" 37 | }, 38 | "operator" : "<", 39 | "right" : { 40 | "kind" : "IntegerLiteral", 41 | "location" : [ 2, 11, 2, 13 ], 42 | "value" : 100 43 | } 44 | }, 45 | "body" : [ { 46 | "kind" : "AssignStmt", 47 | "location" : [ 3, 5, 3, 13 ], 48 | "targets" : [ { 49 | "kind" : "Identifier", 50 | "location" : [ 3, 5, 3, 5 ], 51 | "name" : "x" 52 | } ], 53 | "value" : { 54 | "kind" : "BinaryExpr", 55 | "location" : [ 3, 9, 3, 13 ], 56 | "left" : { 57 | "kind" : "Identifier", 58 | "location" : [ 3, 9, 3, 9 ], 59 | "name" : "x" 60 | }, 61 | "operator" : "+", 62 | "right" : { 63 | "kind" : "IntegerLiteral", 64 | "location" : [ 3, 13, 3, 13 ], 65 | "value" : 1 66 | } 67 | } 68 | } ] 69 | } ], 70 | "errors" : { 71 | "errors" : [ ], 72 | "kind" : "Errors", 73 | "location" : [ 0, 0, 0, 0 ] 74 | } 75 | } -------------------------------------------------------------------------------- /tests/typecheck/str_cat.py: -------------------------------------------------------------------------------- 1 | a:str = "Hello" 2 | b:str = "World" 3 | c:str = "ChocoPy" 4 | 5 | def cat2(a:str, b:str) -> str: 6 | return a + b 7 | 8 | def cat3(a:str, b:str, c:str) -> str: 9 | return a + b + c 10 | 11 | print(cat2(a, b)) 12 | print(cat2("", c)) 13 | print(cat3(a, " ", c)) 14 | print(len(a)) 15 | print(len(cat2(a,a))) 16 | print(len(cat2("",""))) 17 | 18 | -------------------------------------------------------------------------------- /tests/typecheck/str_cat_2.py: -------------------------------------------------------------------------------- 1 | a:str = "no" 2 | b:str = "o" 3 | c:str = "" 4 | d:str = "" 5 | e:str = "" 6 | 7 | def cat2(a:str, b:str) -> str: 8 | return a + b 9 | 10 | def cat3(a:str, b:str, c:str) -> str: 11 | return a + b + c 12 | 13 | c = cat2(b, a) 14 | d = cat2(a, a) 15 | e = cat3(a, b, cat2(b, b)) 16 | 17 | print(c) 18 | print(d) 19 | print(e) 20 | -------------------------------------------------------------------------------- /tests/typecheck/str_cmp.py: -------------------------------------------------------------------------------- 1 | a:str = "Hello" 2 | b:str = "World" 3 | c:str = "ChocoPy" 4 | 5 | def eq(a:str, b:str) -> bool: 6 | return a == b 7 | 8 | def neq(a:str, b:str) -> bool: 9 | return a != b 10 | 11 | print(eq(a,a)) 12 | print(eq(a,b)) 13 | print(neq(a,b)) 14 | print(neq(b,b)) 15 | print(eq(c,a)) 16 | print(neq(c,b)) 17 | 18 | -------------------------------------------------------------------------------- /tests/typecheck/str_get_element.py: -------------------------------------------------------------------------------- 1 | x:str = "abc" 2 | a:str = "" 3 | b:str = "" 4 | c:str = "" 5 | 6 | def str_get(s:str, i:int) -> str: 7 | return s[i] 8 | 9 | a = str_get(x, 0) 10 | b = str_get(x, 1) 11 | c = str_get(x, 2) 12 | print(a) 13 | print(b) 14 | print(c) 15 | -------------------------------------------------------------------------------- /tests/typecheck/str_get_element_oob_1.py: -------------------------------------------------------------------------------- 1 | x:str = "abc" 2 | a:str = "" 3 | 4 | def str_get(s:str, i:int) -> str: 5 | return s[i] 6 | 7 | a = str_get(x, -1) 8 | print(a) 9 | -------------------------------------------------------------------------------- /tests/typecheck/str_get_element_oob_2.py: -------------------------------------------------------------------------------- 1 | x:str = "abc" 2 | a:str = "" 3 | 4 | def str_get(s:str, i:int) -> str: 5 | return s[i] 6 | 7 | a = str_get(x, 3) 8 | print(a) 9 | -------------------------------------------------------------------------------- /tests/typecheck/str_get_element_oob_3.py: -------------------------------------------------------------------------------- 1 | x:str = "" 2 | a:str = "" 3 | 4 | def str_get(s:str, i:int) -> str: 5 | return s[i] 6 | 7 | a = str_get(x, 0) 8 | print(a) 9 | -------------------------------------------------------------------------------- /tests/typecheck/str_len.py: -------------------------------------------------------------------------------- 1 | print(len("ChocoPy")) 2 | -------------------------------------------------------------------------------- /tests/typecheck/str_len.py.ast.typed: -------------------------------------------------------------------------------- 1 | { 2 | "kind" : "Program", 3 | "location" : [ 1, 1, 1, 22 ], 4 | "declarations" : [ ], 5 | "statements" : [ { 6 | "kind" : "ExprStmt", 7 | "location" : [ 1, 1, 1, 21 ], 8 | "expr" : { 9 | "kind" : "CallExpr", 10 | "location" : [ 1, 1, 1, 21 ], 11 | "inferredType" : { 12 | "kind" : "ClassValueType", 13 | "className" : "" 14 | }, 15 | "function" : { 16 | "kind" : "Identifier", 17 | "location" : [ 1, 1, 1, 5 ], 18 | "inferredType" : { 19 | "kind" : "FuncType", 20 | "parameters" : [ { 21 | "kind" : "ClassValueType", 22 | "className" : "object" 23 | } ], 24 | "returnType" : { 25 | "kind" : "ClassValueType", 26 | "className" : "" 27 | } 28 | }, 29 | "name" : "print" 30 | }, 31 | "args" : [ { 32 | "kind" : "CallExpr", 33 | "location" : [ 1, 7, 1, 20 ], 34 | "inferredType" : { 35 | "kind" : "ClassValueType", 36 | "className" : "int" 37 | }, 38 | "function" : { 39 | "kind" : "Identifier", 40 | "location" : [ 1, 7, 1, 9 ], 41 | "inferredType" : { 42 | "kind" : "FuncType", 43 | "parameters" : [ { 44 | "kind" : "ClassValueType", 45 | "className" : "object" 46 | } ], 47 | "returnType" : { 48 | "kind" : "ClassValueType", 49 | "className" : "int" 50 | } 51 | }, 52 | "name" : "len" 53 | }, 54 | "args" : [ { 55 | "kind" : "StringLiteral", 56 | "location" : [ 1, 11, 1, 19 ], 57 | "inferredType" : { 58 | "kind" : "ClassValueType", 59 | "className" : "str" 60 | }, 61 | "value" : "ChocoPy" 62 | } ] 63 | } ] 64 | } 65 | } ], 66 | "errors" : { 67 | "errors" : [ ], 68 | "kind" : "Errors", 69 | "location" : [ 0, 0, 0, 0 ] 70 | } 71 | } -------------------------------------------------------------------------------- /tests/typecheck/strings.py: -------------------------------------------------------------------------------- 1 | x:str = "Hello" 2 | y:str = "World" 3 | z:str = "" 4 | 5 | z = x + y 6 | z = x[0] 7 | x = y = z 8 | 9 | -------------------------------------------------------------------------------- /tests/typecheck/var_assign.py: -------------------------------------------------------------------------------- 1 | x:int = 0 2 | y:object = 1 3 | x = y = 42 4 | print(x) 5 | -------------------------------------------------------------------------------- /wasm.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Runtime support for running WASM compiled from Chocopy 3 | * 4 | * This is a very minimal runtime since the goal was to implement as much as 5 | * possible directly in WASM. 6 | * 7 | * The only imports from JS to WASM are for `console.log` and `console.assert`, 8 | * and the latter isn't even strictly necessary. 9 | * 10 | * The memory buffer is instantiated by JS, but after that it's never written 11 | * to and only used to print strings. 12 | */ 13 | 14 | 15 | const wasm_path = process.argv[2]; 16 | 17 | function logString(offset) { 18 | // first 4 bytes is the length 19 | const length = new Uint32Array(memory.buffer, offset, 1)[0]; 20 | // next [length] bytes is the string contents, encoded as utf-8 21 | const bytes = new Uint8Array(memory.buffer, offset + 4, length); 22 | const string = new TextDecoder('utf8').decode(bytes); 23 | console.log(string); 24 | } 25 | 26 | function logInt(val) { 27 | // cast BigInt to a number for pretty-printing w/o the "n" 28 | // this may truncate or break for values that take >53 bits 29 | console.log(Number(val)); 30 | } 31 | 32 | function logBool(val) { 33 | // this is a 32 bit number, either 1 or 0 34 | console.log(val !== 0); 35 | } 36 | 37 | function assert(val, line) { 38 | if (!val) { 39 | throw new Error("Assertion failed on line " + line.toString()); 40 | } 41 | } 42 | 43 | const memory = new WebAssembly.Memory({ 44 | initial: 10, 45 | maximum: 100 46 | }); 47 | 48 | const importObject = { 49 | imports: { 50 | logString: x => logString(x), 51 | logInt: x => logInt(x), 52 | logBool: x => logBool(x), 53 | assert: (x, y) => assert(x, y) 54 | }, 55 | js: { 56 | mem: memory 57 | }, 58 | }; 59 | 60 | const fs = require('fs'); 61 | 62 | const wasmBuffer = fs.readFileSync(wasm_path); 63 | WebAssembly.instantiate(wasmBuffer, importObject); --------------------------------------------------------------------------------