Remove semicolons after field declarations
This commit is contained in:
		
							
								
								
									
										4
									
								
								Rakefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Rakefile
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
# This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
# obtain one at https://mozilla.org/MPL/2.0/. -}
 | 
			
		||||
# obtain one at https://mozilla.org/MPL/2.0/.
 | 
			
		||||
 | 
			
		||||
require 'pathname'
 | 
			
		||||
require 'open3'
 | 
			
		||||
@@ -21,7 +21,7 @@ directory HOST_GCC
 | 
			
		||||
directory HOST_INSTALL
 | 
			
		||||
 | 
			
		||||
task default: [TMP + 'elna'] do
 | 
			
		||||
  sh (TMP + 'elna').to_path, '--lex', 'source.elna'
 | 
			
		||||
  sh (TMP + 'elna').to_path, '--parse', 'source.elna'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
namespace :boot do
 | 
			
		||||
 
 | 
			
		||||
@@ -454,9 +454,9 @@ optional_statements:
 | 
			
		||||
field_declaration:
 | 
			
		||||
    IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
 | 
			
		||||
required_fields:
 | 
			
		||||
    field_declaration ";" required_fields
 | 
			
		||||
    field_declaration required_fields
 | 
			
		||||
        {
 | 
			
		||||
            std::swap($$, $3);
 | 
			
		||||
            std::swap($$, $2);
 | 
			
		||||
            $$.emplace($$.cbegin(), $1);
 | 
			
		||||
        }
 | 
			
		||||
    | field_declaration { $$.emplace_back($1); }
 | 
			
		||||
 
 | 
			
		||||
@@ -620,7 +620,7 @@ namespace elna::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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										761
									
								
								source.elna
									
									
									
									
									
								
							
							
						
						
									
										761
									
								
								source.elna
									
									
									
									
									
								
							@@ -1,3 +1,6 @@
 | 
			
		||||
(* This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
  v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
  obtain one at https://mozilla.org/MPL/2.0/. *)
 | 
			
		||||
program
 | 
			
		||||
 | 
			
		||||
import dummy
 | 
			
		||||
@@ -78,48 +81,52 @@ type
 | 
			
		||||
	_import
 | 
			
		||||
  )
 | 
			
		||||
  Position* = record
 | 
			
		||||
    line: Word;
 | 
			
		||||
    line: Word
 | 
			
		||||
	column: Word
 | 
			
		||||
  end
 | 
			
		||||
  Location* = record
 | 
			
		||||
    first: Position;
 | 
			
		||||
    first: Position
 | 
			
		||||
	last: Position
 | 
			
		||||
  end
 | 
			
		||||
  SourceFile* = record
 | 
			
		||||
	buffer: [1024]Char;
 | 
			
		||||
	handle: ^FILE;
 | 
			
		||||
	size: Word;
 | 
			
		||||
	buffer: [1024]Char
 | 
			
		||||
	handle: ^FILE
 | 
			
		||||
	size: Word
 | 
			
		||||
	index: Word
 | 
			
		||||
  end
 | 
			
		||||
  FILE* = record end
 | 
			
		||||
  StringBuffer* = record
 | 
			
		||||
    data: ^Byte;
 | 
			
		||||
    size: Word;
 | 
			
		||||
    data: ^Byte
 | 
			
		||||
    size: Word
 | 
			
		||||
    capacity: Word
 | 
			
		||||
  end
 | 
			
		||||
  SourceCode = record
 | 
			
		||||
    position: Position;
 | 
			
		||||
    position: Position
 | 
			
		||||
 | 
			
		||||
	input: ^Byte;
 | 
			
		||||
	empty: proc(^Byte) -> Bool;
 | 
			
		||||
	advance: proc(^Byte);
 | 
			
		||||
	input: ^Byte
 | 
			
		||||
	empty: proc(^Byte) -> Bool
 | 
			
		||||
	advance: proc(^Byte)
 | 
			
		||||
	head: proc(^Byte) -> Char
 | 
			
		||||
  end
 | 
			
		||||
  Token* = record
 | 
			
		||||
    kind: TokenKind;
 | 
			
		||||
    kind: TokenKind
 | 
			
		||||
    value: union
 | 
			
		||||
      int_value: Int;
 | 
			
		||||
      string: String;
 | 
			
		||||
	  boolean_value: Bool;
 | 
			
		||||
      int_value: Int
 | 
			
		||||
      string: String
 | 
			
		||||
	  boolean_value: Bool
 | 
			
		||||
	  char_value: Char
 | 
			
		||||
    end;
 | 
			
		||||
    end
 | 
			
		||||
	location: Location
 | 
			
		||||
  end
 | 
			
		||||
  CommandLine* = record
 | 
			
		||||
    input: ^Char;
 | 
			
		||||
	lex: Bool;
 | 
			
		||||
    input: ^Char
 | 
			
		||||
	lex: Bool
 | 
			
		||||
	parse: Bool
 | 
			
		||||
  end
 | 
			
		||||
  Lexer* = record
 | 
			
		||||
	length: Word
 | 
			
		||||
    data: ^Token
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
(*
 | 
			
		||||
  External procedures.
 | 
			
		||||
@@ -359,7 +366,7 @@ end
 | 
			
		||||
  Token procedures.
 | 
			
		||||
*)
 | 
			
		||||
 | 
			
		||||
proc escape_char(escape: Char, result: ^Char) -> Bool;
 | 
			
		||||
proc lexer_escape(escape: Char, result: ^Char) -> Bool;
 | 
			
		||||
var
 | 
			
		||||
  successful: Bool
 | 
			
		||||
begin
 | 
			
		||||
@@ -405,7 +412,8 @@ begin
 | 
			
		||||
  return successful
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc skip_spaces(source_code: ^SourceCode);
 | 
			
		||||
(* Skip spaces. *)
 | 
			
		||||
proc lexer_spaces(source_code: ^SourceCode);
 | 
			
		||||
var
 | 
			
		||||
  current: Char
 | 
			
		||||
begin
 | 
			
		||||
@@ -419,21 +427,22 @@ begin
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc is_ident(char: Char) -> Bool;
 | 
			
		||||
(* Checker whether the character is allowed in an identificator. *)
 | 
			
		||||
proc lexer_is_ident(char: Char) -> Bool;
 | 
			
		||||
  return is_alnum(char) or char = '_'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc lex_identifier(source_code: ^SourceCode, token_content: ^StringBuffer);
 | 
			
		||||
proc lexer_identifier(source_code: ^SourceCode, token_content: ^StringBuffer);
 | 
			
		||||
var
 | 
			
		||||
  content_length: Word
 | 
			
		||||
begin
 | 
			
		||||
  while ~source_code_empty(source_code) & is_ident(source_code_head(source_code^)) do
 | 
			
		||||
  while ~source_code_empty(source_code) & lexer_is_ident(source_code_head(source_code^)) do
 | 
			
		||||
    string_buffer_push(token_content, source_code_head(source_code^));
 | 
			
		||||
	source_code_advance(source_code)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc lex_comment(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
 | 
			
		||||
proc lexer_comment(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
 | 
			
		||||
var
 | 
			
		||||
  trailing: Word
 | 
			
		||||
begin
 | 
			
		||||
@@ -456,7 +465,7 @@ begin
 | 
			
		||||
  return trailing = 2u
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc lex_character(source_code: ^SourceCode, token_content: ^Char) -> Bool;
 | 
			
		||||
proc lexer_character(source_code: ^SourceCode, token_content: ^Char) -> Bool;
 | 
			
		||||
var
 | 
			
		||||
  successful: Bool
 | 
			
		||||
begin
 | 
			
		||||
@@ -466,7 +475,7 @@ begin
 | 
			
		||||
    if source_code_head(source_code^) = '\\' then
 | 
			
		||||
      source_code_advance(source_code);
 | 
			
		||||
 | 
			
		||||
      successful := ~source_code_empty(source_code) & escape_char(source_code_head(source_code^), token_content)
 | 
			
		||||
      successful := ~source_code_empty(source_code) & lexer_escape(source_code_head(source_code^), token_content)
 | 
			
		||||
	else
 | 
			
		||||
      token_content^ := source_code_head(source_code^);
 | 
			
		||||
	  successful := true
 | 
			
		||||
@@ -478,7 +487,7 @@ begin
 | 
			
		||||
  return successful
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc lex_string(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
 | 
			
		||||
proc lexer_string(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
 | 
			
		||||
var
 | 
			
		||||
  token_end, constructed_string: ^Char
 | 
			
		||||
  token_length: Word
 | 
			
		||||
@@ -488,7 +497,7 @@ begin
 | 
			
		||||
  is_valid := true;
 | 
			
		||||
 | 
			
		||||
  while is_valid & ~source_code_empty(source_code) & source_code_head(source_code^) <> '"' do
 | 
			
		||||
    is_valid := lex_character(source_code, @next_char);
 | 
			
		||||
    is_valid := lexer_character(source_code, @next_char);
 | 
			
		||||
 | 
			
		||||
    if is_valid then
 | 
			
		||||
      string_buffer_push(token_content, next_char)
 | 
			
		||||
@@ -503,7 +512,7 @@ begin
 | 
			
		||||
  return is_valid
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc lex_number(source_code: ^SourceCode, token_content: ^Int);
 | 
			
		||||
proc lexer_number(source_code: ^SourceCode, token_content: ^Int);
 | 
			
		||||
begin
 | 
			
		||||
  token_content^ := 0;
 | 
			
		||||
 | 
			
		||||
@@ -514,7 +523,342 @@ begin
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc print_tokens(tokens: ^Token, tokens_size: Word);
 | 
			
		||||
(* Categorize an identifier. *)
 | 
			
		||||
proc lexer_categorize(token_content: String) -> Token;
 | 
			
		||||
var
 | 
			
		||||
  current_token: Token
 | 
			
		||||
begin
 | 
			
		||||
  if token_content = "if" then
 | 
			
		||||
	current_token.kind := TokenKind._if
 | 
			
		||||
  elsif token_content = "then" then
 | 
			
		||||
	current_token.kind := TokenKind._then
 | 
			
		||||
  elsif token_content = "else" then
 | 
			
		||||
	current_token.kind := TokenKind._else
 | 
			
		||||
  elsif token_content = "elsif" then
 | 
			
		||||
	current_token.kind := TokenKind._elsif
 | 
			
		||||
  elsif token_content = "while" then
 | 
			
		||||
	current_token.kind := TokenKind._while
 | 
			
		||||
  elsif token_content = "do" then
 | 
			
		||||
	current_token.kind := TokenKind._do
 | 
			
		||||
  elsif token_content = "proc" then
 | 
			
		||||
	current_token.kind := TokenKind._proc
 | 
			
		||||
  elsif token_content = "begin" then
 | 
			
		||||
	current_token.kind := TokenKind._begin
 | 
			
		||||
  elsif token_content = "end" then
 | 
			
		||||
	current_token.kind := TokenKind._end
 | 
			
		||||
  elsif token_content = "extern" then
 | 
			
		||||
	current_token.kind := TokenKind._extern
 | 
			
		||||
  elsif token_content = "const" then
 | 
			
		||||
	current_token.kind := TokenKind._const
 | 
			
		||||
  elsif token_content = "var" then
 | 
			
		||||
	current_token.kind := TokenKind._var
 | 
			
		||||
  elsif token_content = "case" then
 | 
			
		||||
	current_token.kind := TokenKind._case
 | 
			
		||||
  elsif token_content = "of" then
 | 
			
		||||
	current_token.kind := TokenKind._of
 | 
			
		||||
  elsif token_content = "type" then
 | 
			
		||||
	current_token.kind := TokenKind._type
 | 
			
		||||
  elsif token_content = "record" then
 | 
			
		||||
	current_token.kind := TokenKind._record
 | 
			
		||||
  elsif token_content = "union" then
 | 
			
		||||
	current_token.kind := TokenKind._union
 | 
			
		||||
  elsif token_content = "true" then
 | 
			
		||||
	current_token.kind := TokenKind.boolean;
 | 
			
		||||
	current_token.value.boolean_value := true
 | 
			
		||||
  elsif token_content = "false" then
 | 
			
		||||
	current_token.kind := TokenKind.boolean;
 | 
			
		||||
	current_token.value.boolean_value := false
 | 
			
		||||
  elsif token_content = "nil" then
 | 
			
		||||
	current_token.kind := TokenKind.null
 | 
			
		||||
  elsif token_content = "or" then
 | 
			
		||||
	current_token.kind := TokenKind._or
 | 
			
		||||
  elsif token_content = "return" then
 | 
			
		||||
	current_token.kind := TokenKind._return
 | 
			
		||||
  elsif token_content = "cast" then
 | 
			
		||||
	current_token.kind := TokenKind._cast
 | 
			
		||||
  elsif token_content = "defer" then
 | 
			
		||||
	current_token.kind := TokenKind._defer
 | 
			
		||||
  elsif token_content = "program" then
 | 
			
		||||
	current_token.kind := TokenKind._program
 | 
			
		||||
  elsif token_content = "module" then
 | 
			
		||||
    current_token.kind := TokenKind._module
 | 
			
		||||
  elsif token_content = "import" then
 | 
			
		||||
    current_token.kind := TokenKind._import
 | 
			
		||||
  else
 | 
			
		||||
	current_token.kind := TokenKind.identifier;
 | 
			
		||||
	current_token.value.string := string_dup(token_content)
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  return current_token
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc lexer_add_token(lexer: ^Lexer, token: Token);
 | 
			
		||||
var
 | 
			
		||||
  new_length: Word
 | 
			
		||||
begin
 | 
			
		||||
  new_length := lexer^.length + 1u;
 | 
			
		||||
  lexer^.data := cast(reallocarray(cast(lexer^.data: ^Byte), new_length, #size(Token)): ^Token);
 | 
			
		||||
  (lexer^.data + lexer^.length)^ := token;
 | 
			
		||||
  lexer^.length := new_length
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
(* Read the next token from the input. *)
 | 
			
		||||
proc lexer_next(source_code: SourceCode, token_buffer: ^StringBuffer) -> Token;
 | 
			
		||||
var
 | 
			
		||||
  current_token: Token
 | 
			
		||||
  first_char: Char
 | 
			
		||||
begin
 | 
			
		||||
  current_token.kind := TokenKind.unknown;
 | 
			
		||||
 | 
			
		||||
  first_char := source_code_head(source_code);
 | 
			
		||||
 | 
			
		||||
  if is_alpha(first_char) or first_char = '_' then
 | 
			
		||||
    lexer_identifier(@source_code, token_buffer);
 | 
			
		||||
    current_token := lexer_categorize(string_buffer_clear(token_buffer))
 | 
			
		||||
  elsif first_char = '#' then
 | 
			
		||||
	source_code_advance(@source_code);
 | 
			
		||||
	lexer_identifier(@source_code, token_buffer);
 | 
			
		||||
 | 
			
		||||
	current_token.kind := TokenKind.trait;
 | 
			
		||||
	current_token.value.string := string_dup(string_buffer_clear(token_buffer))
 | 
			
		||||
  elsif is_digit(first_char) then
 | 
			
		||||
	lexer_number(@source_code, @current_token.value.int_value);
 | 
			
		||||
 | 
			
		||||
	if source_code_expect(@source_code, 'u') then
 | 
			
		||||
	  current_token.kind := TokenKind.word;
 | 
			
		||||
      source_code_advance(@source_code)
 | 
			
		||||
	else
 | 
			
		||||
	  current_token.kind := TokenKind.integer
 | 
			
		||||
	end
 | 
			
		||||
  elsif first_char = '(' then
 | 
			
		||||
	source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
	if source_code_empty(@source_code) then
 | 
			
		||||
	  current_token.kind := TokenKind.left_paren
 | 
			
		||||
	elsif source_code_head(source_code) = '*' then
 | 
			
		||||
	  source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
	  if lexer_comment(@source_code, token_buffer) then
 | 
			
		||||
	    current_token.value.string := string_dup(string_buffer_clear(token_buffer));
 | 
			
		||||
	    current_token.kind := TokenKind.comment
 | 
			
		||||
	  else
 | 
			
		||||
	    current_token.kind := TokenKind.unknown
 | 
			
		||||
	  end
 | 
			
		||||
	else
 | 
			
		||||
	  current_token.kind := TokenKind.left_paren
 | 
			
		||||
	end
 | 
			
		||||
  elsif first_char = ')' then
 | 
			
		||||
	current_token.kind := TokenKind.right_paren;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '\'' then
 | 
			
		||||
    source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
	if lexer_character(@source_code, @current_token.value.char_value) & source_code_expect(@source_code, '\'') then
 | 
			
		||||
		current_token.kind := TokenKind.character;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	else
 | 
			
		||||
	  current_token.kind := TokenKind.unknown
 | 
			
		||||
	end
 | 
			
		||||
  elsif first_char = '"' then
 | 
			
		||||
    source_code_advance(@source_code);
 | 
			
		||||
	
 | 
			
		||||
    if lexer_string(@source_code, token_buffer) then
 | 
			
		||||
	  current_token.kind := TokenKind.string;
 | 
			
		||||
	  current_token.value.string := string_dup(string_buffer_clear(token_buffer))
 | 
			
		||||
	else
 | 
			
		||||
	  current_token.kind := TokenKind.unknown
 | 
			
		||||
	end
 | 
			
		||||
  elsif first_char = '[' then
 | 
			
		||||
	current_token.kind := TokenKind.left_square;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = ']' then
 | 
			
		||||
	current_token.kind := TokenKind.right_square;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '>' then
 | 
			
		||||
	source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
    if source_code_empty(@source_code) then
 | 
			
		||||
	  current_token.kind := TokenKind.greater_than
 | 
			
		||||
	elsif source_code_head(source_code) = '=' then
 | 
			
		||||
	  current_token.kind := TokenKind.greater_equal;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif source_code_head(source_code) = '>' then
 | 
			
		||||
	  current_token.kind := TokenKind.shift_right;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	else
 | 
			
		||||
	  current_token.kind := TokenKind.greater_than
 | 
			
		||||
	end
 | 
			
		||||
  elsif first_char = '<' then
 | 
			
		||||
	source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
	if source_code_empty(@source_code) then
 | 
			
		||||
	  current_token.kind := TokenKind.less_than
 | 
			
		||||
	elsif source_code_head(source_code) = '=' then
 | 
			
		||||
	  current_token.kind := TokenKind.less_equal;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif source_code_head(source_code) = '<' then
 | 
			
		||||
	  current_token.kind := TokenKind.shift_left;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif source_code_head(source_code) = '>' then
 | 
			
		||||
	  current_token.kind := TokenKind.not_equal;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	else
 | 
			
		||||
	  current_token.kind := TokenKind.less_than
 | 
			
		||||
	end
 | 
			
		||||
  elsif first_char = '=' then
 | 
			
		||||
	current_token.kind := TokenKind.equal;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = ';' then
 | 
			
		||||
	current_token.kind := TokenKind.semicolon;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '.' then
 | 
			
		||||
	current_token.kind := TokenKind.dot;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = ',' then
 | 
			
		||||
	current_token.kind := TokenKind.comma;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '+' then
 | 
			
		||||
	current_token.kind := TokenKind.plus;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '-' then
 | 
			
		||||
	source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
    if source_code_empty(@source_code) then
 | 
			
		||||
	  current_token.kind := TokenKind.minus
 | 
			
		||||
	elsif source_code_head(source_code) = '>' then
 | 
			
		||||
	  current_token.kind := TokenKind.arrow;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	else
 | 
			
		||||
	  current_token.kind := TokenKind.minus
 | 
			
		||||
	end
 | 
			
		||||
  elsif first_char = '*' then
 | 
			
		||||
	current_token.kind := TokenKind.multiplication;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '/' then
 | 
			
		||||
	current_token.kind := TokenKind.division;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '%' then
 | 
			
		||||
	current_token.kind := TokenKind.remainder;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = ':' then
 | 
			
		||||
	source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
	if source_code_empty(@source_code) then
 | 
			
		||||
	  current_token.kind := TokenKind.colon
 | 
			
		||||
	elsif source_code_head(source_code) = '=' then
 | 
			
		||||
	  current_token.kind := TokenKind.assignment;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	else
 | 
			
		||||
	  current_token.kind := TokenKind.colon
 | 
			
		||||
	end
 | 
			
		||||
  elsif first_char = '^' then
 | 
			
		||||
	current_token.kind := TokenKind.hat;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '@' then
 | 
			
		||||
	current_token.kind := TokenKind.at;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '!' then
 | 
			
		||||
	current_token.kind := TokenKind.exclamation;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '&' then
 | 
			
		||||
	current_token.kind := TokenKind.and;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '~' then
 | 
			
		||||
	current_token.kind := TokenKind.not;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  elsif first_char = '|' then
 | 
			
		||||
	current_token.kind := TokenKind.pipe;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  else
 | 
			
		||||
	current_token.kind := TokenKind.unknown;
 | 
			
		||||
	source_code_advance(@source_code)
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  return current_token
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
(* Split the source text into tokens. *)
 | 
			
		||||
proc lexer_text(source_code: SourceCode) -> Lexer;
 | 
			
		||||
var
 | 
			
		||||
  current_token: Token
 | 
			
		||||
  token_buffer: StringBuffer
 | 
			
		||||
  lexer: Lexer
 | 
			
		||||
begin
 | 
			
		||||
  lexer := Lexer(0u, nil);
 | 
			
		||||
  token_buffer := string_buffer_new();
 | 
			
		||||
 | 
			
		||||
  lexer_spaces(@source_code);
 | 
			
		||||
 | 
			
		||||
  while ~source_code_empty(@source_code) do
 | 
			
		||||
	current_token := lexer_next(source_code, @token_buffer);
 | 
			
		||||
 | 
			
		||||
	if current_token.kind <> TokenKind.unknown then
 | 
			
		||||
	  lexer_add_token(@lexer, current_token);
 | 
			
		||||
      lexer_spaces(@source_code)
 | 
			
		||||
	else
 | 
			
		||||
	  write_s("Lexical analysis error on \"");
 | 
			
		||||
	  write_c(source_code_head(source_code));
 | 
			
		||||
	  write_s("\".\n")
 | 
			
		||||
	end
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  return lexer
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
(*
 | 
			
		||||
  Command line handling.
 | 
			
		||||
*)
 | 
			
		||||
 | 
			
		||||
proc parse_command_line*(argc: Int, argv: ^^Char) -> ^CommandLine;
 | 
			
		||||
var
 | 
			
		||||
  parameter: ^^Char
 | 
			
		||||
  i: Int
 | 
			
		||||
  result: ^CommandLine
 | 
			
		||||
begin
 | 
			
		||||
  i := 1;
 | 
			
		||||
  result := cast(malloc(#size(CommandLine)): ^CommandLine);
 | 
			
		||||
  result^.lex := false;
 | 
			
		||||
  result^.parse := false;
 | 
			
		||||
  result^.input := nil;
 | 
			
		||||
 | 
			
		||||
  while i < argc & result <> nil do
 | 
			
		||||
    parameter := argv + i;
 | 
			
		||||
 | 
			
		||||
    if strcmp(parameter^, "--lex\0".ptr) = 0 then
 | 
			
		||||
      result^.lex := true
 | 
			
		||||
    elsif strcmp(parameter^, "--parse\0".ptr) = 0 then
 | 
			
		||||
      result^.parse := true
 | 
			
		||||
    elsif parameter^^ <> '-' then
 | 
			
		||||
	  if result^.input <> nil then
 | 
			
		||||
		write_s("Fatal error: Only one source file can be given.\n");
 | 
			
		||||
		result := nil
 | 
			
		||||
	  else
 | 
			
		||||
        result^.input := parameter^
 | 
			
		||||
	  end
 | 
			
		||||
    else
 | 
			
		||||
      write_s("Fatal error: Unknown command line options: ");
 | 
			
		||||
 | 
			
		||||
      write_z(parameter^);
 | 
			
		||||
      write_s(".\n");
 | 
			
		||||
 | 
			
		||||
      result := nil
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
    i := i + 1
 | 
			
		||||
  end;
 | 
			
		||||
  if result <> nil & result^.input = nil then
 | 
			
		||||
    write_s("Fatal error: no input files.\n");
 | 
			
		||||
	result := nil
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  return result
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
(*
 | 
			
		||||
  Parser.
 | 
			
		||||
*)
 | 
			
		||||
 | 
			
		||||
proc parse(tokens: ^Token, tokens_size: Word);
 | 
			
		||||
var
 | 
			
		||||
  current_token: ^Token
 | 
			
		||||
  i: Word
 | 
			
		||||
@@ -673,319 +1017,27 @@ begin
 | 
			
		||||
  write_c('\n')
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc categorize_identifier(token_content: String) -> Token;
 | 
			
		||||
var
 | 
			
		||||
  current_token: Token
 | 
			
		||||
begin
 | 
			
		||||
  if token_content = "if" then
 | 
			
		||||
	current_token.kind := TokenKind._if
 | 
			
		||||
  elsif token_content = "then" then
 | 
			
		||||
	current_token.kind := TokenKind._then
 | 
			
		||||
  elsif token_content = "else" then
 | 
			
		||||
	current_token.kind := TokenKind._else
 | 
			
		||||
  elsif token_content = "elsif" then
 | 
			
		||||
	current_token.kind := TokenKind._elsif
 | 
			
		||||
  elsif token_content = "while" then
 | 
			
		||||
	current_token.kind := TokenKind._while
 | 
			
		||||
  elsif token_content = "do" then
 | 
			
		||||
	current_token.kind := TokenKind._do
 | 
			
		||||
  elsif token_content = "proc" then
 | 
			
		||||
	current_token.kind := TokenKind._proc
 | 
			
		||||
  elsif token_content = "begin" then
 | 
			
		||||
	current_token.kind := TokenKind._begin
 | 
			
		||||
  elsif token_content = "end" then
 | 
			
		||||
	current_token.kind := TokenKind._end
 | 
			
		||||
  elsif token_content = "extern" then
 | 
			
		||||
	current_token.kind := TokenKind._extern
 | 
			
		||||
  elsif token_content = "const" then
 | 
			
		||||
	current_token.kind := TokenKind._const
 | 
			
		||||
  elsif token_content = "var" then
 | 
			
		||||
	current_token.kind := TokenKind._var
 | 
			
		||||
  elsif token_content = "case" then
 | 
			
		||||
	current_token.kind := TokenKind._case
 | 
			
		||||
  elsif token_content = "of" then
 | 
			
		||||
	current_token.kind := TokenKind._of
 | 
			
		||||
  elsif token_content = "type" then
 | 
			
		||||
	current_token.kind := TokenKind._type
 | 
			
		||||
  elsif token_content = "record" then
 | 
			
		||||
	current_token.kind := TokenKind._record
 | 
			
		||||
  elsif token_content = "union" then
 | 
			
		||||
	current_token.kind := TokenKind._union
 | 
			
		||||
  elsif token_content = "true" then
 | 
			
		||||
	current_token.kind := TokenKind.boolean;
 | 
			
		||||
	current_token.value.boolean_value := true
 | 
			
		||||
  elsif token_content = "false" then
 | 
			
		||||
	current_token.kind := TokenKind.boolean;
 | 
			
		||||
	current_token.value.boolean_value := false
 | 
			
		||||
  elsif token_content = "nil" then
 | 
			
		||||
	current_token.kind := TokenKind.null
 | 
			
		||||
  elsif token_content = "or" then
 | 
			
		||||
	current_token.kind := TokenKind._or
 | 
			
		||||
  elsif token_content = "return" then
 | 
			
		||||
	current_token.kind := TokenKind._return
 | 
			
		||||
  elsif token_content = "cast" then
 | 
			
		||||
	current_token.kind := TokenKind._cast
 | 
			
		||||
  elsif token_content = "defer" then
 | 
			
		||||
	current_token.kind := TokenKind._defer
 | 
			
		||||
  elsif token_content = "program" then
 | 
			
		||||
	current_token.kind := TokenKind._program
 | 
			
		||||
  elsif token_content = "module" then
 | 
			
		||||
    current_token.kind := TokenKind._module
 | 
			
		||||
  elsif token_content = "import" then
 | 
			
		||||
    current_token.kind := TokenKind._import
 | 
			
		||||
  else
 | 
			
		||||
	current_token.kind := TokenKind.identifier;
 | 
			
		||||
	current_token.value.string := string_dup(token_content)
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  return current_token
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc tokenize(source_code: SourceCode, tokens_size: ^Word) -> ^Token;
 | 
			
		||||
var
 | 
			
		||||
  tokens, current_token: ^Token
 | 
			
		||||
  first_char: Char
 | 
			
		||||
  token_buffer: StringBuffer
 | 
			
		||||
begin
 | 
			
		||||
  tokens_size^ := 0u;
 | 
			
		||||
  tokens := nil;
 | 
			
		||||
  token_buffer := string_buffer_new();
 | 
			
		||||
 | 
			
		||||
  skip_spaces(@source_code);
 | 
			
		||||
 | 
			
		||||
  while ~source_code_empty(@source_code) do
 | 
			
		||||
	tokens := cast(reallocarray(cast(tokens: ^Byte), tokens_size^ + 1u, #size(Token)): ^Token);
 | 
			
		||||
    current_token := tokens + tokens_size^;
 | 
			
		||||
	first_char := source_code_head(source_code);
 | 
			
		||||
 | 
			
		||||
    if is_alpha(first_char) or first_char = '_' then
 | 
			
		||||
      lex_identifier(@source_code, @token_buffer);
 | 
			
		||||
      current_token^ := categorize_identifier(string_buffer_clear(@token_buffer))
 | 
			
		||||
	elsif first_char = '#' then
 | 
			
		||||
	  source_code_advance(@source_code);
 | 
			
		||||
	  lex_identifier(@source_code, @token_buffer);
 | 
			
		||||
 | 
			
		||||
	  current_token^.kind := TokenKind.trait;
 | 
			
		||||
	  current_token^.value.string := string_dup(string_buffer_clear(@token_buffer))
 | 
			
		||||
	elsif is_digit(first_char) then
 | 
			
		||||
	  lex_number(@source_code, @current_token^.value.int_value);
 | 
			
		||||
 | 
			
		||||
	  if source_code_expect(@source_code, 'u') then
 | 
			
		||||
	    current_token^.kind := TokenKind.word;
 | 
			
		||||
        source_code_advance(@source_code)
 | 
			
		||||
	  else
 | 
			
		||||
	    current_token^.kind := TokenKind.integer
 | 
			
		||||
	  end
 | 
			
		||||
	elsif first_char = '(' then
 | 
			
		||||
	  source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
	  if source_code_empty(@source_code) then
 | 
			
		||||
	    current_token^.kind := TokenKind.left_paren
 | 
			
		||||
	  elsif source_code_head(source_code) = '*' then
 | 
			
		||||
	    source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
		if lex_comment(@source_code, @token_buffer) then
 | 
			
		||||
	      current_token^.value.string := string_dup(string_buffer_clear(@token_buffer));
 | 
			
		||||
		  current_token^.kind := TokenKind.comment
 | 
			
		||||
		else
 | 
			
		||||
	      current_token^.kind := TokenKind.unknown
 | 
			
		||||
		end
 | 
			
		||||
	  else
 | 
			
		||||
	    current_token^.kind := TokenKind.left_paren
 | 
			
		||||
	  end
 | 
			
		||||
	elsif first_char = ')' then
 | 
			
		||||
	  current_token^.kind := TokenKind.right_paren;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '\'' then
 | 
			
		||||
      source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
	  if lex_character(@source_code, @current_token^.value.char_value) & source_code_expect(@source_code, '\'') then
 | 
			
		||||
	  	current_token^.kind := TokenKind.character;
 | 
			
		||||
	    source_code_advance(@source_code)
 | 
			
		||||
	  else
 | 
			
		||||
	    current_token^.kind := TokenKind.unknown
 | 
			
		||||
	  end
 | 
			
		||||
	elsif first_char = '"' then
 | 
			
		||||
      source_code_advance(@source_code);
 | 
			
		||||
	  
 | 
			
		||||
      if lex_string(@source_code, @token_buffer) then
 | 
			
		||||
		current_token^.kind := TokenKind.string;
 | 
			
		||||
		current_token^.value.string := string_dup(string_buffer_clear(@token_buffer))
 | 
			
		||||
	  else
 | 
			
		||||
	    current_token^.kind := TokenKind.unknown
 | 
			
		||||
	  end
 | 
			
		||||
	elsif first_char = '[' then
 | 
			
		||||
	  current_token^.kind := TokenKind.left_square;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = ']' then
 | 
			
		||||
	  current_token^.kind := TokenKind.right_square;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '>' then
 | 
			
		||||
	  source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
      if source_code_empty(@source_code) then
 | 
			
		||||
	    current_token^.kind := TokenKind.greater_than
 | 
			
		||||
	  elsif source_code_head(source_code) = '=' then
 | 
			
		||||
	    current_token^.kind := TokenKind.greater_equal;
 | 
			
		||||
	    source_code_advance(@source_code)
 | 
			
		||||
	  elsif source_code_head(source_code) = '>' then
 | 
			
		||||
	    current_token^.kind := TokenKind.shift_right;
 | 
			
		||||
	    source_code_advance(@source_code)
 | 
			
		||||
	  else
 | 
			
		||||
	    current_token^.kind := TokenKind.greater_than
 | 
			
		||||
	  end
 | 
			
		||||
	elsif first_char = '<' then
 | 
			
		||||
	  source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
	  if source_code_empty(@source_code) then
 | 
			
		||||
	    current_token^.kind := TokenKind.less_than
 | 
			
		||||
	  elsif source_code_head(source_code) = '=' then
 | 
			
		||||
	    current_token^.kind := TokenKind.less_equal;
 | 
			
		||||
	    source_code_advance(@source_code)
 | 
			
		||||
	  elsif source_code_head(source_code) = '<' then
 | 
			
		||||
	    current_token^.kind := TokenKind.shift_left;
 | 
			
		||||
	    source_code_advance(@source_code)
 | 
			
		||||
	  elsif source_code_head(source_code) = '>' then
 | 
			
		||||
	    current_token^.kind := TokenKind.not_equal;
 | 
			
		||||
	    source_code_advance(@source_code)
 | 
			
		||||
	  else
 | 
			
		||||
	    current_token^.kind := TokenKind.less_than
 | 
			
		||||
	  end
 | 
			
		||||
	elsif first_char = '=' then
 | 
			
		||||
	  current_token^.kind := TokenKind.equal;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = ';' then
 | 
			
		||||
	  current_token^.kind := TokenKind.semicolon;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '.' then
 | 
			
		||||
	  current_token^.kind := TokenKind.dot;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = ',' then
 | 
			
		||||
	  current_token^.kind := TokenKind.comma;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '+' then
 | 
			
		||||
	  current_token^.kind := TokenKind.plus;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '-' then
 | 
			
		||||
	  source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
      if source_code_empty(@source_code) then
 | 
			
		||||
	    current_token^.kind := TokenKind.minus
 | 
			
		||||
	  elsif source_code_head(source_code) = '>' then
 | 
			
		||||
	    current_token^.kind := TokenKind.arrow;
 | 
			
		||||
	    source_code_advance(@source_code)
 | 
			
		||||
	  else
 | 
			
		||||
	    current_token^.kind := TokenKind.minus
 | 
			
		||||
	  end
 | 
			
		||||
	elsif first_char = '*' then
 | 
			
		||||
	  current_token^.kind := TokenKind.multiplication;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '/' then
 | 
			
		||||
	  current_token^.kind := TokenKind.division;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '%' then
 | 
			
		||||
	  current_token^.kind := TokenKind.remainder;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = ':' then
 | 
			
		||||
	  source_code_advance(@source_code);
 | 
			
		||||
 | 
			
		||||
	  if source_code_empty(@source_code) then
 | 
			
		||||
	    current_token^.kind := TokenKind.colon
 | 
			
		||||
	  elsif source_code_head(source_code) = '=' then
 | 
			
		||||
	    current_token^.kind := TokenKind.assignment;
 | 
			
		||||
	    source_code_advance(@source_code)
 | 
			
		||||
	  else
 | 
			
		||||
	    current_token^.kind := TokenKind.colon
 | 
			
		||||
	  end
 | 
			
		||||
	elsif first_char = '^' then
 | 
			
		||||
	  current_token^.kind := TokenKind.hat;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '@' then
 | 
			
		||||
	  current_token^.kind := TokenKind.at;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '!' then
 | 
			
		||||
	  current_token^.kind := TokenKind.exclamation;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '&' then
 | 
			
		||||
	  current_token^.kind := TokenKind.and;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '~' then
 | 
			
		||||
	  current_token^.kind := TokenKind.not;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	elsif first_char = '|' then
 | 
			
		||||
	  current_token^.kind := TokenKind.pipe;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	else
 | 
			
		||||
	  current_token^.kind := TokenKind.unknown;
 | 
			
		||||
	  source_code_advance(@source_code)
 | 
			
		||||
	end;
 | 
			
		||||
 | 
			
		||||
	if current_token^.kind <> TokenKind.unknown then
 | 
			
		||||
      tokens_size^ := tokens_size^ + 1u;
 | 
			
		||||
      skip_spaces(@source_code)
 | 
			
		||||
	else
 | 
			
		||||
	  write_s("Lexical analysis error on \"");
 | 
			
		||||
	  write_c(first_char);
 | 
			
		||||
	  write_s("\".\n")
 | 
			
		||||
	end
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  return tokens
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
(*
 | 
			
		||||
  Command line handling.
 | 
			
		||||
*)
 | 
			
		||||
 | 
			
		||||
proc parse_command_line*(argc: Int, argv: ^^Char) -> ^CommandLine;
 | 
			
		||||
var
 | 
			
		||||
  parameter: ^^Char
 | 
			
		||||
  i: Int
 | 
			
		||||
  result: ^CommandLine
 | 
			
		||||
begin
 | 
			
		||||
  i := 1;
 | 
			
		||||
  result := cast(malloc(#size(CommandLine)): ^CommandLine);
 | 
			
		||||
  result^.lex := false;
 | 
			
		||||
  result^.parse := false;
 | 
			
		||||
  result^.input := nil;
 | 
			
		||||
 | 
			
		||||
  while i < argc & result <> nil do
 | 
			
		||||
    parameter := argv + i;
 | 
			
		||||
 | 
			
		||||
    if strcmp(parameter^, "--lex\0".ptr) = 0 then
 | 
			
		||||
      result^.lex := true
 | 
			
		||||
    elsif strcmp(parameter^, "--parse\0".ptr) = 0 then
 | 
			
		||||
      result^.parse := true
 | 
			
		||||
    elsif parameter^^ <> '-' then
 | 
			
		||||
	  if result^.input <> nil then
 | 
			
		||||
		write_s("Fatal error: Only one source file can be given.\n");
 | 
			
		||||
		result := nil
 | 
			
		||||
	  else
 | 
			
		||||
        result^.input := parameter^
 | 
			
		||||
	  end
 | 
			
		||||
    else
 | 
			
		||||
      write_s("Fatal error: Unknown command line options: ");
 | 
			
		||||
 | 
			
		||||
      write_z(parameter^);
 | 
			
		||||
      write_s(".\n");
 | 
			
		||||
 | 
			
		||||
      result := nil
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
    i := i + 1
 | 
			
		||||
  end;
 | 
			
		||||
  if result <> nil & result^.input = nil then
 | 
			
		||||
    write_s("Fatal error: no input files.\n");
 | 
			
		||||
	result := nil
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  return result
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
(*
 | 
			
		||||
  Compilation entry.
 | 
			
		||||
*)
 | 
			
		||||
 | 
			
		||||
proc compile_in_stages(command_line: ^CommandLine, source_code: SourceCode) -> Int;
 | 
			
		||||
var
 | 
			
		||||
  return_code: Int
 | 
			
		||||
  lexer: Lexer
 | 
			
		||||
begin
 | 
			
		||||
  return_code := 0;
 | 
			
		||||
 | 
			
		||||
  if command_line^.lex or command_line^.parse then
 | 
			
		||||
    lexer := lexer_text(source_code)
 | 
			
		||||
  end;
 | 
			
		||||
  if command_line^.parse then
 | 
			
		||||
    parse(lexer.data, lexer.length)
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  return return_code
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc process(argc: Int, argv: ^^Char) -> Int;
 | 
			
		||||
var
 | 
			
		||||
  tokens: ^Token
 | 
			
		||||
@@ -993,6 +1045,7 @@ var
 | 
			
		||||
  source_code: SourceCode
 | 
			
		||||
  command_line: ^CommandLine
 | 
			
		||||
  return_code: Int
 | 
			
		||||
  source_file: ^SourceFile
 | 
			
		||||
begin
 | 
			
		||||
  return_code := 0;
 | 
			
		||||
 | 
			
		||||
@@ -1002,26 +1055,26 @@ begin
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  if return_code = 0 then
 | 
			
		||||
	source_code.position := Position(1u, 1u);
 | 
			
		||||
    source_file := read_source(command_line^.input);
 | 
			
		||||
 | 
			
		||||
	source_code.input := cast(read_source(command_line^.input): ^Byte);
 | 
			
		||||
	if source_file = nil then
 | 
			
		||||
	  perror(command_line^.input);
 | 
			
		||||
	  return_code := 3
 | 
			
		||||
	end
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  if return_code = 0 then
 | 
			
		||||
    defer
 | 
			
		||||
	  fclose(source_file^.handle)
 | 
			
		||||
	end;
 | 
			
		||||
 | 
			
		||||
	source_code.position := Position(1u, 1u);
 | 
			
		||||
	source_code.input := cast(source_file: ^Byte);
 | 
			
		||||
	source_code.empty := source_file_empty;
 | 
			
		||||
	source_code.head := source_file_head;
 | 
			
		||||
	source_code.advance := source_file_advance;
 | 
			
		||||
 | 
			
		||||
	if source_code.input = nil then
 | 
			
		||||
      perror(command_line^.input);
 | 
			
		||||
      return_code := 3
 | 
			
		||||
	end
 | 
			
		||||
  end;
 | 
			
		||||
  if return_code = 0 then
 | 
			
		||||
    tokens := tokenize(source_code, @tokens_size);
 | 
			
		||||
 | 
			
		||||
    fclose(cast(source_code.input: ^SourceFile)^.handle);
 | 
			
		||||
 | 
			
		||||
    if command_line^.lex then
 | 
			
		||||
      print_tokens(tokens, tokens_size)
 | 
			
		||||
    end
 | 
			
		||||
    return_code := compile_in_stages(command_line, source_code)
 | 
			
		||||
  end;
 | 
			
		||||
  return return_code
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user