Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions bootstrap/build.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
./vixc0 main.vix > main.ll
clang -c main.ll -o vixc1.o
clang -o vixc1 vixc1.o helper.o $(llvm-config --ldflags --libs)
set -e
./vixc1 -obj main.vix -o vixc1.o
clang -o vixc2 vixc1.o helper.o $(llvm-config --ldflags --libs)
8 changes: 8 additions & 0 deletions bootstrap/error.vix
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ pub fn error_code_for_type(error_type: string, message: string): string
if (str_starts_with(msg, "entry function 'main'") == 1) { return "E4002" }
return "E4000"
}
if (error_type == "SemanticWarning")
{
if (str_starts_with(msg, "unused variable '") == 1) { return "W4001" }
if (str_starts_with(msg, "no 'main' function defined") == 1) { return "W4002" }
if (str_starts_with(msg, "entry function 'main'") == 1) { return "W4003" }
return "W4000"
}
return "E0000"
}

Expand Down Expand Up @@ -358,6 +365,7 @@ pub fn format_header(is_warning: i32, error_type: string, message: string): stri
"TypeError" -> diag_blue()
"NameError" -> diag_cyan()
"SemanticError" -> diag_yellow()
"SemanticWarning" -> diag_yellow()
_ -> diag_red()
}
let code = error_code_for_type(error_type, message)
Expand Down
4 changes: 4 additions & 0 deletions bootstrap/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ const char *vix_diag_yellow(void) { return "\033[33m"; }

const char *vix_diag_reset(void) { return "\033[0m"; }

void vix_print_stderr(const char *s) {
fputs(s, stderr);
}

void vix_reset_vars(void) { var_count = 0; }

void vix_set_var(const char *name, LLVMValueRef value) {
Expand Down
51,403 changes: 0 additions & 51,403 deletions bootstrap/main.ll

This file was deleted.

122 changes: 96 additions & 26 deletions bootstrap/main.vix
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "lexer.vix"
import "parser.vix"
import "ast.vix"
import "typeinfer.vix"
import "typeck.vix"
import "semantic.vix"
import "codegen.vix"
import "error.vix"
Expand All @@ -14,6 +14,8 @@ extern "C"
fn fputs(s: string, file: ptr): i32
fn fseek(file: ptr, offset: i64, whence: i32): i32
fn ftell(file: ptr): i64
fn system(command: ptr): i32
fn vix_print_stderr(s: string)
fn malloc(size: usize): string
fn vix_diag_red(): string
fn vix_diag_yellow(): string
Expand All @@ -35,7 +37,7 @@ fn compiler_mode(arg: string): ?string
{
if (arg == "-h" or arg == "--help") { return Some("--help") }
if (arg == "-v" or arg == "--version") { return Some("--version") }
if (arg == "--lex" or arg == "--parse-stats" or arg == "--parser" or arg == "--ast" or arg == "--typeinfer" or arg == "--tyinfer" or arg == "--semantic" or arg == "--check") { return Some(arg) }
if (arg == "--lex" or arg == "--parse-stats" or arg == "--parser" or arg == "--ast" or arg == "--typeinfer" or arg == "--tyinfer" or arg == "--semantic" or arg == "--check" or arg == "-ll" or arg == "-obj" or arg == "-exe") { return Some(arg) }
return None
}

Expand All @@ -54,6 +56,30 @@ fn strip_vix_ext(name: string): string
return name
}

fn shell_command(command: string): i32
{
return system(command)
}

fn diag_print(text: string)
{
vix_print_stderr(text)
}

fn ir_output_path(filename: string, output: string): string
{
if (output != "") { return output }
return strip_vix_ext(filename) + ".ll"
}

fn artifact_output_path(filename: string, output: string, emit: string): string
{
if (output != "") { return output }
let base = strip_vix_ext(filename)
if (emit == "exe") { return base }
return base + ".o"
}

fn print_help(): i32
{
print("OVERVIEW: Vix Compiler LLVM Bootstrap")
Expand All @@ -63,6 +89,8 @@ fn print_help(): i32
print("OPTIONS:")
print(" -o <file> Write output to <file>")
print(" -ll [file] Emit LLVM IR to <file> (default: <input>.ll)")
print(" -obj Emit object file (default: <input>.o)")
print(" -exe Emit executable (default: <input>)")
print(" --check Syntax & type check only")
print(" --lex Print tokens to stdout")
print(" --parse-stats Print lightweight parser input statistics")
Expand Down Expand Up @@ -94,11 +122,11 @@ fn run_mode(mode: string, src: string, filename: string, emit: string, output: s
match mode
{
"--lex" -> {
print(tokenize_debug(src))
diag_print(tokenize_debug(src))
return Some(0)
}
"--parse-stats" -> {
print(parse_program_stats(src, filename))
diag_print(parse_program_stats(src, filename))
return Some(0)
}
_ -> {}
Expand All @@ -111,22 +139,22 @@ fn run_mode(mode: string, src: string, filename: string, emit: string, output: s
"--parser" -> {
if (program.ok == 0)
{
print(program.error)
diag_print(program.error)
}
else
{
print(ast_program_debug(program))
diag_print(ast_program_debug(program))
}
return Some(0)
}
"--ast" -> {
if (program.ok == 0)
{
print(program.error)
diag_print(program.error)
}
else
{
print(ast(program))
diag_print(ast(program))
}
return Some(0)
}
Expand All @@ -135,39 +163,43 @@ fn run_mode(mode: string, src: string, filename: string, emit: string, output: s

if (program.ok == 0)
{
print(program.error)
diag_print(program.error)
return Some(1)
}

let semantic_result = semantic_check_program(program, src, filename)
match mode
{
"--semantic" -> {
print(semantic_result_debug(semantic_result))
diag_print(semantic_result_debug(semantic_result))
return Some(0)
}
_ -> {}
}

if (semantic_result.error_count > 0)
{
print(semantic_result_debug(semantic_result))
diag_print(semantic_result_debug(semantic_result))
return Some(1)
}
if (semantic_result.warning_count > 0)
{
diag_print(semantic_result_debug(semantic_result))
}

let infer_result = infer(program)
let infer_result = typeck_check_program(program)
match mode
{
"--typeinfer" | "--tyinfer" -> {
print(typeinfer_result_debug(infer_result, src, filename))
diag_print(typeck_result_debug(infer_result, src, filename))
return Some(0)
}
_ -> {}
}

if (infer_result.ok == 0)
{
print(typeinfer_result_debug(infer_result, src, filename))
diag_print(typeck_result_debug(infer_result, src, filename))
return Some(1)
}

Expand All @@ -183,10 +215,38 @@ fn run_mode(mode: string, src: string, filename: string, emit: string, output: s
print(ir)
return None
}
let base = strip_vix_ext(filename)
let path = if (output != "") { output } else { base + ".ll" }
write_text_file(path, ir)
print(path)
let mut ir_path = ""
if (emit == "ir")
{
ir_path = ir_output_path(filename, output)
}
else
{
ir_path = strip_vix_ext(filename) + ".ll"
}
write_text_file(ir_path, ir)
if (emit == "ir")
{
print(ir_path)
return Some(0)
}

let artifact_path = artifact_output_path(filename, output, emit)
let mut command = ""
if (emit == "-obj")
{
command = "clang -c " + ir_path + " -o " + artifact_path
}
else
{
command = "clang " + ir_path + " helper.o -o " + artifact_path + " -L /usr/lib -l LLVM-22"
}
if (shell_command(command) != 0)
{
diag_print("vixc0: error: failed to build '" + artifact_path + "'")
return Some(1)
}
print(artifact_path)
return Some(0)
}

Expand All @@ -195,7 +255,7 @@ fn write_text_file(path: string, content: string): i32
let file = fopen(path, "w")
if (file == 0)
{
print("vixc0: error: cannot write file '" + path + "'")
diag_print("vixc0: error: cannot write file '" + path + "'")
return 1
}
fputs(content, file)
Expand Down Expand Up @@ -245,15 +305,14 @@ fn main(argc: i32, argv: ptr): i32
}
elif (arg == "-o")
{
emit = "ir"
if (i + 1 < argc)
{
i += 1
output = argv[i]
}
else
{
print("vixc0: error: '-o' requires an argument")
diag_print("vixc0: error: '-o' requires an argument")
return 1
}
}
Expand All @@ -270,29 +329,40 @@ fn main(argc: i32, argv: ptr): i32
}
}
}
elif (arg == "-obj")
{
emit = "-obj"
}
elif (arg == "-exe")
{
emit = "-exe"
}
else
{
match compiler_mode(arg)
{
Some(next_mode) -> {
if (next_mode == "--help") { want_help = 1 }
elif (next_mode == "--version") { want_version = 1 }
elif (next_mode == "-ll") { emit = "ir" }
elif (next_mode == "-obj") { emit = "-obj" }
elif (next_mode == "-exe") { emit = "-exe" }
else { mode = next_mode }
}
None -> match source_file_arg(arg)
{
Some(path) -> {
if (has_input == 1)
{
print("vixc0: error: multiple input files not supported")
diag_print("vixc0: error: multiple input files not supported")
return 1
}
src = read_source_file(path)
filename = path
has_input = 1
}
None -> {
print("vixc0: error: unrecognized command-line option '" + arg + "'")
diag_print("vixc0: error: unrecognized command-line option '" + arg + "'")
return 1
}
}
Expand All @@ -306,14 +376,14 @@ fn main(argc: i32, argv: ptr): i32

if (has_input == 0)
{
print("vixc0: fatal error: no input files")
print("compilation terminated.")
diag_print("vixc0: fatal error: no input files")
diag_print("compilation terminated.")
return 1
}

if (src == "")
{
print("vixc0: error: cannot read file '" + filename + "'")
diag_print("vixc0: error: cannot read file '" + filename + "'")
return 1
}

Expand Down
8 changes: 6 additions & 2 deletions bootstrap/parser.vix
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,8 @@ pub fn parse_for_statement(parser: &Parser): i32
parser_advance(parser)
parser_expect_text(parser, "(")
if (parser.ok == 0) { return -1 }
let name_line = parser_line(parser)
let name_col = parser_col(parser)
let name = parser_text(parser)
if (parser_expect_kind(parser, tk_ident()) == 0) { return -1 }
parser_expect_text(parser, "in")
Expand All @@ -913,7 +915,7 @@ pub fn parse_for_statement(parser: &Parser): i32
if (parser.ok == 0) { return -1 }
let body_idx = parse_block_statement(parser)
if (parser.ok == 0) { return -1 }
return parser_stmt_at(parser, ast_stmt_for_range(parser.store, name, start_idx, end_idx, body_idx), line, col)
return parser_stmt_at(parser, ast_stmt_for_range(parser.store, name, start_idx, end_idx, body_idx), name_line, name_col)
}

pub fn parse_match_pattern(parser: &Parser): i32
Expand Down Expand Up @@ -1082,6 +1084,8 @@ pub fn parse_statement(parser: &Parser): i32
is_mut = 1
parser_advance(parser)
}
let name_line = parser_line(parser)
let name_col = parser_col(parser)
let name = parser_text(parser)
if (parser_expect_kind(parser, tk_ident()) == 0) { return -1 }
let mut type_text = ""
Expand All @@ -1096,7 +1100,7 @@ pub fn parse_statement(parser: &Parser): i32
let expr_idx = parse_expression(parser)
if (parser.ok == 0) { return -1 }
parser_accept_text(parser, ";")
return parser_stmt_at(parser, ast_stmt_let_typed_mut(parser.store, name, type_text, expr_idx, is_mut), line, col)
return parser_stmt_at(parser, ast_stmt_let_typed_mut(parser.store, name, type_text, expr_idx, is_mut), name_line, name_col)
}
if (stmt_text == "return")
{
Expand Down
Loading