diff --git a/boot/ast.cc b/boot/ast.cc index d023b86..0091962 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -1012,6 +1012,10 @@ namespace boot return "or"; case binary_operator::exclusive_disjunction: return "xor"; + case binary_operator::shift_left: + return "<<"; + case binary_operator::shift_right: + return ">>"; } __builtin_unreachable(); }; diff --git a/boot/lexer.ll b/boot/lexer.ll index 4fc2664..5837940 100644 --- a/boot/lexer.ll +++ b/boot/lexer.ll @@ -137,9 +137,6 @@ return { cast { return yy::parser::make_CAST(this->location); } -sizeof { - return yy::parser::make_SIZEOF(this->location); - } defer { return yy::parser::make_DEFER(this->location); } @@ -232,6 +229,12 @@ defer { \] { return yy::parser::make_RIGHT_SQUARE(this->location); } +\<\< { + return yy::parser::make_SHIFT_LEFT(this->location); + } +\>\> { + return yy::parser::make_SHIFT_RIGHT(this->location); + } \>= { return yy::parser::make_GREATER_EQUAL(this->location); } diff --git a/boot/parser.yy b/boot/parser.yy index 9de5c3b..49f3af9 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -85,7 +85,7 @@ along with GCC; see the file COPYING3. If not see %token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION %token BEGIN_BLOCK END_BLOCK EXTERN DEFER %token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA -%token AND OR NOT CAST SIZEOF +%token AND OR NOT CAST SHIFT_LEFT SHIFT_RIGHT %token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS %token PLUS MINUS MULTIPLICATION DIVISION REMAINDER %token ASSIGNMENT COLON HAT AT NIL ARROW @@ -344,6 +344,16 @@ expression: $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, elna::boot::binary_operator::exclusive_disjunction); } + | expression SHIFT_LEFT expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::shift_left); + } + | expression SHIFT_RIGHT expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::shift_right); + } unary: AT operand { @@ -448,7 +458,7 @@ variable_declarations: | variable_declaration { $$.emplace_back(std::move($1)); } variable_part: /* no variable declarations */ {} - | VAR variable_declarations SEMICOLON { std::swap($$, $2); } + | VAR variable_declarations { std::swap($$, $2); } constant_definition: identifier_definition EQUALS literal { $$ = new elna::boot::constant_definition(elna::boot::make_position(@1), $1.first, $1.second, $3); diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 91abf3d..cecfcee 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -575,10 +575,11 @@ namespace gcc } if (left_type != right_type && !are_compatible_pointers(left_type, right) - && !are_compatible_pointers(right_type, left)) + && !are_compatible_pointers(right_type, left) + && !(is_integral_type(left_type) && right_type == elna_word_type_node)) { error_at(expression_location, - "invalid operands of type %s and %s for operator %s", + "invalid operands of type '%s' and '%s' for operator %s", print_type(left_type).c_str(), print_type(right_type).c_str(), boot::print_binary_operator(expression->operation())); this->current_expression = error_mark_node; @@ -628,6 +629,16 @@ namespace gcc case boot::binary_operator::not_equals: this->current_expression = build_equality_operation(expression, left, right); break; + case boot::binary_operator::shift_left: + this->current_expression = build_binary_operation( + is_numeric_type(left_type) && right_type == elna_word_type_node, + expression, LSHIFT_EXPR, left, right, left_type); + break; + case boot::binary_operator::shift_right: + this->current_expression = build_binary_operation( + is_numeric_type(left_type) && right_type == elna_word_type_node, + expression, RSHIFT_EXPR, left, right, left_type); + break; } } diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc index 2b7bb0a..f36faf7 100644 --- a/gcc/elna-tree.cc +++ b/gcc/elna-tree.cc @@ -195,7 +195,7 @@ namespace gcc else { error_at(expression_location, - "invalid operands of type %s and %s for operator %s", + "invalid operands of type '%s' and '%s' for operator %s", print_type(left_type).c_str(), print_type(right_type).c_str(), elna::boot::print_binary_operator(expression->operation())); return error_mark_node; diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 10800d2..06054e5 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -42,7 +42,9 @@ namespace boot greater_equal, disjunction, conjunction, - exclusive_disjunction + exclusive_disjunction, + shift_left, + shift_right }; enum class unary_operator diff --git a/source.elna b/source.elna index 5c4df3c..3868369 100644 --- a/source.elna +++ b/source.elna @@ -173,7 +173,7 @@ end proc write_i(value: Int); var digit: Int, n: Word, - buffer: array 10 of Char; + buffer: array 10 of Char begin n := 10u; @@ -230,7 +230,7 @@ end proc string_dup(origin: String) -> String; var - copy: pointer to Char; + copy: pointer to Char begin copy := cast(malloc(origin.length): pointer to Char); strncpy(copy, origin.ptr, origin.length); @@ -244,7 +244,7 @@ end proc make_position() -> Position; var - result: Position; + result: Position begin return Position(1u, 1u) end @@ -253,7 +253,7 @@ proc read_source(filename: pointer to Char, result: pointer to String) -> Bool; var input_file: pointer to FILE, source_size: Int, - input: pointer to Byte; + input: pointer to Byte begin input_file := fopen(filename, "rb\0".ptr); @@ -349,7 +349,7 @@ end proc lex_identifier(source_code: pointer to SourceCode, token_content: pointer to String); var - content_length: Word; + content_length: Word begin content_length := 0u; token_content^ := source_code^.text; @@ -363,7 +363,7 @@ end proc lex_comment(source_code: pointer to SourceCode, token_content: pointer to String) -> Bool; var - content_length: Word; + content_length: Word begin content_length := 0u; token_content^ := source_code^.text; @@ -401,7 +401,7 @@ var token_end: pointer to Char, constructed_string: pointer to Char, token_length: Word, - is_valid: Bool; + is_valid: Bool begin token_end := input; @@ -439,7 +439,7 @@ end proc print_tokens(tokens: pointer to Token, tokens_size: Word); var current_token: pointer to Token, - i: Word; + i: Word begin i := 0u; while i < tokens_size do @@ -583,7 +583,7 @@ end proc categorize_identifier(token_content: String) -> Token; var - current_token: Token; + current_token: Token begin if "if" = token_content then current_token.kind := TOKEN_IF @@ -662,7 +662,7 @@ var current_token: pointer to Token, token_length: Word, first_char: Char, - token_content: String; + token_content: String begin tokens_size^ := 0u; tokens := nil; @@ -827,7 +827,7 @@ end proc parse_constant_definition(tokens: pointer to pointer to Token, tokens_size: pointer to Word) -> pointer to ConstantDefinition; var - result: pointer to ConstantDefinition; + result: pointer to ConstantDefinition begin result := cast(calloc(1u, ConstantDefinition.size): pointer to ConstantDefinition); @@ -851,7 +851,7 @@ end proc parse_program(tokens: pointer to pointer to Token, tokens_size: pointer to Word) -> pointer to Program; var result: pointer to Program, - current_constant: pointer to pointer to ConstantDefinition; + current_constant: pointer to pointer to ConstantDefinition begin result := cast(calloc(1u, Program.size): pointer to Program); @@ -885,7 +885,7 @@ proc parse_command_line*(argc: Int, argv: pointer to pointer to Char) -> pointer var parameter: pointer to pointer to Char, i: Int, - result: pointer to CommandLine; + result: pointer to CommandLine begin i := 1; result := cast(malloc(CommandLine.size): pointer to CommandLine); @@ -927,7 +927,7 @@ var tokens: pointer to Token, tokens_size: Word, source_code: SourceCode, - command_line: pointer to CommandLine; + command_line: pointer to CommandLine begin command_line := parse_command_line(argc, argv); if command_line = nil then