diff --git a/boot/stage15/cl.elna b/boot/stage15/cl.elna index f2d2cab..6511bd7 100644 --- a/boot/stage15/cl.elna +++ b/boot/stage15/cl.elna @@ -10,6 +10,8 @@ (* - Record declarations are supported. Access is done with generated procedures, record_name_get_field and record_name_set_field. Record size can be queried with record_name_size(). *) +(* - Program modules start with the "program;" keyword. *) +(* - nil literal. *) type ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited); @@ -153,7 +155,8 @@ type named_type_expression, type_declaration, module_declaration, - record_type_expression + record_type_expression, + null ); InfoKind = (type_info, parameter_info, temporary_info, procedure_info); TypeKind = (primitive, enumeration, _record); @@ -1300,6 +1303,10 @@ begin this^ := kind end; +proc _nil_node_size(); + return 4 +end; + proc _integer_literal_node_size(); return 12 end; @@ -1350,6 +1357,19 @@ begin return result end; +proc _elna_parser_nil(); +var + result: Word; + literal_size: Word; +begin + literal_size := _nil_node_size(); + result := _allocate(literal_size); + + _elna_lexer_skip_token(); + _node_set_kind(result, NodeKind.null); + return result +end; + proc _elna_tac_integer_literal(integer_literal_node: Word); var integer_token: Word; @@ -1362,6 +1382,11 @@ begin return _elna_tac_load_immediate(ElnaTacRegister.t0, integer_token, integer_length) end; +proc _elna_tac_nil(nil_node: Word); +begin + return _elna_tac_load_immediate(ElnaTacRegister.t0, 0, 0) +end; + proc _character_literal_node_size(); return 12 end; @@ -1587,6 +1612,8 @@ begin parser_node := _elna_parser_integer_literal() elsif token_kind = ElnaLexerKind.string then parser_node := _elna_parser_string_literal() + elsif token_kind = ElnaLexerKind.null then + parser_node := _elna_parser_nil() elsif token_kind = ElnaLexerKind.identifier then parser_node := _elna_parser_variable_expression() end; @@ -1658,6 +1685,8 @@ begin instruction := _elna_tac_string_literal(parser_node) elsif node_kind = NodeKind.integer_literal then instruction := _elna_tac_integer_literal(parser_node) + elsif node_kind = NodeKind.null then + instruction := _elna_tac_nil(parser_node) else instruction := _elna_tac_variable_expression(parser_node, symbol_table); is_address^ := 1 diff --git a/boot/stage16/cl.elna b/boot/stage16/cl.elna index e99efbd..32bedfb 100644 --- a/boot/stage16/cl.elna +++ b/boot/stage16/cl.elna @@ -34,6 +34,9 @@ type value: Word; length: Word end; + _nil_node = record + kind: Word + end; _variable_expression = record kind: Word; name: Word; @@ -345,7 +348,8 @@ type named_type_expression, type_declaration, module_declaration, - record_type_expression + record_type_expression, + null ); InfoKind = (type_info, parameter_info, temporary_info, procedure_info); TypeKind = (primitive, enumeration, _record); @@ -979,6 +983,19 @@ begin return result end; +proc elna_rtl_unary(tac_instruction: Word, rtl_operator: Word, next_instruction: Word); +var + result: Word; +begin + result := elna_rtl_load_operand_value(tac_instruction, 2, ElnaRtlRegister.t0); + next_instruction^ := elna_rtl_instruction_create(rtl_operator); + elna_rtl_copy_operand(tac_instruction, 1, result); + elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.register, ElnaRtlRegister.t0); + result := ElnaInstructionList_set_next(result, next_instruction^); + + return result +end; + proc elna_rtl_instruction(tac_instruction: Word, next_instruction: Word); var result: Word; @@ -992,7 +1009,7 @@ begin instruction_size := elna_rtl_instruction_size(); result := malloc(instruction_size); instruction_kind := _elna_tac_instruction_get_kind(tac_instruction); - next_instruction^ := 0; + next_instruction^ := nil; if instruction_kind = ElnaTacOperator.get_address then operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, 2); @@ -1134,13 +1151,9 @@ begin elsif instruction_kind = ElnaTacOperator.not_equal then result := elna_rtl_binary_equality(tac_instruction, ElnaRtlOperator.snez, next_instruction) elsif instruction_kind = ElnaTacOperator.negate then - result := elna_rtl_instruction_create(ElnaRtlOperator.neg); - elna_rtl_copy_operand(tac_instruction, 1, result); - elna_rtl_copy_operand(tac_instruction, 2, result) + result := elna_rtl_unary(tac_instruction, ElnaRtlOperator.neg, next_instruction) elsif instruction_kind = ElnaTacOperator.complement then - result := elna_rtl_instruction_create(ElnaRtlOperator.not); - elna_rtl_copy_operand(tac_instruction, 1, result); - elna_rtl_copy_operand(tac_instruction, 2, result) + result := elna_rtl_unary(tac_instruction, ElnaRtlOperator.not, next_instruction) elsif instruction_kind = ElnaTacOperator.jump then result := elna_rtl_instruction_create(ElnaRtlOperator.j); elna_rtl_copy_operand(tac_instruction, 1, result) @@ -1543,6 +1556,18 @@ begin return result end; +proc _elna_parser_nil(); +var + result: Word; +begin + _elna_lexer_skip_token(); + + result := malloc(_nil_node_size()); + _nil_node_set_kind(result, NodeKind.null); + + return result +end; + proc _elna_tac_integer_literal(integer_literal_node: Word, operand_type: Word, operand_value: Word, operand_length: Word); begin operand_type^ := ElnaTacOperand.immediate; @@ -1552,6 +1577,15 @@ begin return 0 end; +proc _elna_tac_nil(nil_node: Word, operand_type: Word, operand_value: Word, operand_length: Word); +begin + operand_type^ := ElnaTacOperand.immediate; + operand_value^ := 0; + operand_length^ := 0; + + return 0 +end; + proc _elna_parser_character_literal(); var character: Word; @@ -1684,6 +1718,8 @@ begin parser_node := _elna_parser_integer_literal() elsif token_kind = ElnaLexerKind.string then parser_node := _elna_parser_string_literal() + elsif token_kind = ElnaLexerKind.null then + parser_node := _elna_parser_nil() elsif token_kind = ElnaLexerKind.identifier then parser_node := _elna_parser_variable_expression() end; @@ -1735,6 +1771,8 @@ begin instruction := _elna_tac_string_literal(parser_node, operand_type, operand_value, operand_length) elsif node_kind = NodeKind.integer_literal then instruction := _elna_tac_integer_literal(parser_node, operand_type, operand_value, operand_length) + elsif node_kind = NodeKind.null then + instruction := _elna_tac_nil(parser_node, operand_type, operand_value, operand_length) else instruction := _elna_tac_variable_expression(parser_node, symbol_table, operand_type, operand_value, operand_length) end; @@ -1826,7 +1864,7 @@ begin operand_length^ := 0; elna_instruction_list_concatenate(first_instruction, instruction) - else + elsif operator = 0 then instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); _elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^); @@ -1841,12 +1879,12 @@ begin if operator = '-' then instruction := _elna_tac_instruction_create(ElnaTacOperator.negate); _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); - _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.temporary, 6, 0); + _elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^); elna_instruction_list_concatenate(first_instruction, instruction) elsif operator = '~' then instruction := _elna_tac_instruction_create(ElnaTacOperator.complement); _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); - _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.temporary, 6, 0); + _elna_tac_instruction_set_operand(instruction, 2, operand_type^, operand_value^, operand_length^); elna_instruction_list_concatenate(first_instruction, instruction) end; return first_instruction