Skip to content

Commit

Permalink
feat: preprocessor to inject compiler version
Browse files Browse the repository at this point in the history
  • Loading branch information
myuon committed Jul 23, 2023
1 parent 88e2bd3 commit 5dc5e9a
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 11 deletions.
45 changes: 34 additions & 11 deletions quartz/compiler.qz
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import quartz::ast;
import quartz::ir;
import quartz::value;
import quartz::location;
import quartz::preprocessor;

struct LoadedModule {
path: Path,
Expand All @@ -26,10 +27,10 @@ module Compiler {
};
}

fun load_module(self, path: Path, skip_errors: bool): vec[Path] or error {
fun load_module(self, path: Path, skip_errors: bool, preprocess: bool): vec[Path] or error {
let input = file_read(format("{}.qz", path.join("/")));

return self.register_module(path, input, skip_errors).try;
return self.register_module(path, input, skip_errors, preprocess).try;
}

fun matches(self, path: Path): LoadedModule? {
Expand All @@ -42,13 +43,29 @@ module Compiler {
return nil;
}

fun register_module(self, path: Path, input: string, skip_errors: bool): vec[Path] or error {
fun register_module(
self,
path: Path,
input: string,
skip_errors: bool,
preprocess: bool,
): vec[Path] or error {
let lexer = Lexer::new();
lexer.run(input).try;

let parser = Parser::new();
let module_ = parser.run(lexer.tokens, skip_errors).try;

if preprocess {
let preprocessor = Preprocessor::new();
preprocessor.run(
module_,
struct {
version: "1.0.0",
},
).try;
}

self.loaded.push(LoadedModule {
path: path,
source: input,
Expand All @@ -58,12 +75,18 @@ module Compiler {
return parser.imports;
}

fun parse(self, input: string, load_path: Path?, skip_errors: bool): Module or error {
fun parse(
self,
input: string,
load_path: Path?,
skip_errors: bool,
preprocess: bool,
): Module or error {
let main_path = Path::new("main");
if load_path != nil {
main_path = load_path!;
}
let imports = self.register_module(main_path, input, skip_errors).try;
let imports = self.register_module(main_path, input, skip_errors, preprocess).try;

let visited = make[map[string, bool]]();
visited.insert(main_path.join("_"), true);
Expand All @@ -75,7 +98,7 @@ module Compiler {
continue;
}

imports.extend(self.load_module(path, skip_errors).try);
imports.extend(self.load_module(path, skip_errors, preprocess).try);
visited.insert(path.join("_"), true);
}

Expand Down Expand Up @@ -107,7 +130,7 @@ module Compiler {
skip_errors: bool,
validate_address: bool,
): string or error {
let module_ = self.parse(input, nil, skip_errors).try;
let module_ = self.parse(input, nil, skip_errors, true).try;

let typechecker = Typechecker::new();
let n or err = typechecker.run(module_, main_path);
Expand Down Expand Up @@ -165,7 +188,7 @@ module Compiler {
},
message: string,
}] {
let module_ or err = self.parse(input, nil, true);
let module_ or err = self.parse(input, nil, true, false);
if err != nil {
return make[vec[struct {
start: struct {
Expand Down Expand Up @@ -264,7 +287,7 @@ module Compiler {
fun check_type(self, filepath: string, input: string, line: i32, column: i32): string or error {
let path = Path::new("main");

let module_ = self.parse(input, nil, true).try;
let module_ = self.parse(input, nil, true, false).try;

let position = find_line_column_from_position(input, line, column);

Expand All @@ -286,7 +309,7 @@ module Compiler {
label: string,
text: string,
}] or error {
let module_ = self.parse(input, nil, true).try;
let module_ = self.parse(input, nil, true, false).try;
let position = find_line_column_from_position(input, line, column);

let typechecker = Typechecker::new();
Expand All @@ -312,7 +335,7 @@ module Compiler {
column: i32,
},
} or error {
let module_ = self.parse(input, path?, true).try;
let module_ = self.parse(input, path?, true, false).try;
let position = find_line_column_from_position(input, line, column);

let typechecker = Typechecker::new();
Expand Down
1 change: 1 addition & 0 deletions quartz/main.qz
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import quartz::location;
import quartz::formatter;
import quartz::json;
import quartz::errors;
import quartz::preprocessor;

fun assert_eq_string(a: string, b: string) {
if !a.equal(b) {
Expand Down
93 changes: 93 additions & 0 deletions quartz/preprocessor.qz
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import quartz::ast;

struct Preprocessor {
config: struct {
version: string,
},
}

module Preprocessor {
fun new(): Preprocessor {
return Preprocessor {
config: struct {
version: "",
},
};
}

fun run(
self,
m: Module,
config: struct {
version: string,
},
): nil or error {
self.config = config;

return self.module_(m).try;
}

fun module_(self, m: Module): nil or error {
for d in m.decls {
self.decl(d.data).try;
}

return nil;
}

fun decl(self, d: Decl): nil or error {
if d.t_func != nil {
self.block(d.t_func!.body).try;
}

return nil;
}

fun block(self, lb: LBlock): nil or error {
let b = lb.data;
let index = 0;

while index < b.block.length {
let s = b.block.at(index).data;
if s.t_attribute != nil {
let next = b.block.at(index + 1);
self.process_attribute_for_statement(s.t_attribute!, next).try;

index = index + 1;
}

index = index + 1;
}

return nil;
}

fun process_attribute_for_statement(self, lattr: LAttribute, ls: LStatement): nil or error {
let attr = lattr.data;
if attr.name.data == "compiler" {
let arg = attr.args.at(0).data;
if arg == "version" && ls.data.t_let != nil {
let value = ls.data.t_let!.expr.data;
if value.t_string != nil {
ls.data.t_let!.expr.data = Expression {
t_string: struct {
value: self.config.version,
raw: self.config.version,
},
};

return nil;
}

return _ or error::new("expected string literal");
}

return _ or error::new("unknown compiler attribute");
} else {
return _ or error::new("unknown attribute");
}

return nil;
}
}

0 comments on commit 5dc5e9a

Please sign in to comment.