diff --git a/boot/stage19/cl.elna b/boot/stage19/cl.elna index c47b8e5..0f0b832 100644 --- a/boot/stage19/cl.elna +++ b/boot/stage19/cl.elna @@ -275,6 +275,17 @@ type length: Word; _type: Word end; + ElnaTreeExpressionList = record + expression: ^ElnaTreeBinaryExpression; + next: Word + end; + ElnaTreeCall = record + kind: ElnaTreeKind; + next: Word; + callee: ^ElnaTreeVariableExpression; + arguments: ^ElnaTreeExpressionList; + count: Word + end; (* Symbol table information. *) ElnaSymbolInfoKind = (type_info, parameter_info, temporary_info, procedure_info); @@ -2226,52 +2237,20 @@ begin return first_instruction end; -(* 4 bytes node kind + 4 byte pointer to variable expression + 4 * 7 for arguments. *) -proc _call_size(); - return 44 -end; - -proc _call_get_name(this: Word); -begin - this := this + 8; - return this^ -end; - -proc _call_set_name(this: Word, value: Word); -begin - this := this + 8; - this^ := value -end; - -proc _call_get_argument(this: Word, n: Word); -begin - n := n * 4; - this := this + 8; - this := this + n; - return this^ -end; - -proc _call_set_argument(this: Word, n: Word, value: Word); -begin - n := n * 4; - this := this + 8; - this := this + n; - this^ := value -end; - proc elna_parser_call(callee: Word); var - parsed_expression: Word; - result: ^ElnaTreeStatement; + result: ^ElnaTreeCall; argument_number: Word; token_kind: Word; + argument_entry: ^ElnaTreeExpressionList; begin - result := malloc(_call_size()); + result := malloc(#size(ElnaTreeCall)); result^.kind := ElnaTreeKind.call; result^.next := nil; + result^.arguments := nil; argument_number := 1; - _call_set_name(result, callee); + result^.callee := callee; _elna_lexer_read_token(@token_kind); _elna_lexer_skip_token(); @@ -2283,8 +2262,16 @@ begin end; .elna_parser_call_loop; - parsed_expression := elna_parser_binary_expression(); - _call_set_argument(result, argument_number, parsed_expression); + if result^.arguments = nil then + result^.arguments := malloc(#size(ElnaTreeExpressionList)); + argument_entry := result^.arguments + else + argument_entry^.next := malloc(#size(ElnaTreeExpressionList)); + argument_entry := argument_entry^.next + end; + argument_entry^.next := nil; + argument_entry^.expression := elna_parser_binary_expression(); + argument_number := argument_number + 1; _elna_lexer_read_token(@token_kind); _elna_lexer_skip_token(); @@ -2294,17 +2281,14 @@ begin end; .elna_parser_call_end; - (* Set the trailing argument to nil. *) - _call_set_argument(result, argument_number, nil); + (* Save the number of arguments. *) + result^.count := argument_number - 1; return result end; -proc elna_tac_call(parsed_call: Word, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word); +proc elna_tac_call(parsed_call: ^ElnaTreeCall, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word); var - argument_count: Word; - name_length: Word; - name: Word; parsed_expression: ^ElnaTreeVariableExpression; instruction: Word; first_instruction: Word; @@ -2312,28 +2296,19 @@ var argument_type: Word; argument_value: Word; argument_length: Word; - arguments_operand: Word; + arguments_operand: ^ElnaTacOperand; call_instruction: Word; + argument_entry: ^ElnaTreeExpressionList; name_buffer: Word; + argument_count: Word; begin - parsed_expression := _call_get_name(parsed_call); - name := parsed_expression^.name; - name_length := parsed_expression^.length; - argument_count := 0; - first_instruction := 0; - - .elna_tac_call_count; - parsed_expression := _call_get_argument(parsed_call, argument_count + 1); - - if parsed_expression <> nil ten - argument_count := argument_count + 1; - goto elna_tac_call_count - end; - arguments_operand := malloc(argument_count * 12); + parsed_expression := parsed_call^.callee; + first_instruction := nil; + arguments_operand := malloc(parsed_call^.count * #size(ElnaTacOperand)); call_instruction := elna_tac_instruction_create(ElnaTacOperator.proc_call); - elna_tac_instruction_set_operand(call_instruction, 1, ElnaTacKind.symbol, name, name_length); - elna_tac_instruction_set_operand(call_instruction, 2, ElnaTacKind.list, arguments_operand, argument_count); + elna_tac_instruction_set_operand(call_instruction, 1, ElnaTacKind.symbol, parsed_expression^.name, parsed_expression^.length); + elna_tac_instruction_set_operand(call_instruction, 2, ElnaTacKind.list, arguments_operand, parsed_call^.count); elna_tac_instruction_set_operand(call_instruction, 3, ElnaTacKind.pseudo, "$unary", 6); operand_type^ := ElnaTacKind.pseudo; @@ -2341,22 +2316,21 @@ begin operand_length^ := 6; argument_count := 0; + argument_entry := parsed_call^.arguments; .elna_tac_call_loop; - parsed_expression := _call_get_argument(parsed_call, argument_count + 1); - if parsed_expression = 0 then - goto elna_tac_call_finalize - else + if argument_entry <> nil then argument_type := 0; argument_value := 0; argument_length := 0; - instruction := elna_tac_binary_expression(parsed_expression, symbol_table, @argument_type, @argument_value, @argument_length); - if first_instruction = 0 then + instruction := elna_tac_binary_expression(argument_entry^.expression, symbol_table, + @argument_type, @argument_value, @argument_length); + if first_instruction = nil then first_instruction := instruction else elna_instruction_list_concatenate(current_instruction, instruction) end; - if instruction <> 0 then + if instruction <> nil then current_instruction := instruction end; @@ -2373,18 +2347,15 @@ begin end; current_instruction := instruction; - arguments_operand^ := ElnaTacKind.pseudo; - arguments_operand := arguments_operand + 4; - arguments_operand^ := name_buffer; - arguments_operand := arguments_operand + 4; - arguments_operand^ := 4; - arguments_operand := arguments_operand + 4; + arguments_operand^.kind := ElnaTacKind.pseudo; + arguments_operand^.value := name_buffer; + arguments_operand^.length := 4; + arguments_operand := arguments_operand + #size(ElnaTacOperand); + argument_entry := argument_entry^.next; argument_count := argument_count + 1; goto elna_tac_call_loop end; - .elna_tac_call_finalize; - if first_instruction = nil then first_instruction := call_instruction else @@ -4184,19 +4155,16 @@ begin elna_type_binary_expression(parser_node^.returned, symbol_table) end; -proc elna_type_call(parser_node: Word, symbol_table: Word); +proc elna_type_call(parser_node: ^ElnaTreeCall, symbol_table: Word); var - current_argument: Word; - argument_tree: Word; + argument_tree: ^ElnaTreeExpressionList; begin - current_argument := 1; + argument_tree := parser_node^.arguments; .elna_type_call_argument; - argument_tree := _call_get_argument(parser_node, current_argument); - if argument_tree <> nil then - elna_type_binary_expression(argument_tree, symbol_table); - current_argument := current_argument + 1; + elna_type_binary_expression(argument_tree^.expression, symbol_table); + argument_tree := argument_tree^.next; goto elna_type_call_argument end