Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: compiler attributes #82

Merged
merged 11 commits into from
Jul 29, 2023
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
2 changes: 1 addition & 1 deletion quartz-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "quartz-mode",
"displayName": "quartz-mode",
"description": "",
"version": "0.5.4",
"version": "0.5.6",
"engines": {
"vscode": "^1.76.0"
},
Expand Down
46 changes: 21 additions & 25 deletions quartz-vscode/server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,19 @@ import { exec } from "child_process";
import * as path from "path";
import * as util from "util";

let globalControllers: AbortController[] = [];

const execAsync_ = util.promisify(exec);

const execAsync = async (command: string) => {
if (globalControllers.length > 3) {
globalControllers[0].abort();
globalControllers = globalControllers.slice(1);
}

const controller = new AbortController();
const { signal } = controller;
globalControllers.push(controller);

setTimeout(() => {
try {
controller.abort();
} catch (err) {
console.log(`Aborted: ${err}`);
}
}, 10000);
}, 30000);

const child = await execAsync_(command, { signal });

Expand Down Expand Up @@ -73,23 +65,27 @@ documents.onDidChangeContent(async (change) => {
`quartz check ${file} --project ${path.join(file, "..", "..")}`
);
if (cargo.stdout) {
const errors: {
message: string;
start: [number, number];
end: [number, number];
}[] = JSON.parse(cargo.stdout);

errors.forEach((error) => {
diagnostics.push({
severity: 1,
range: {
start: { line: error.start[0], character: error.start[1] },
end: { line: error.end[0], character: error.end[1] },
},
message: error.message,
source: "ex",
try {
const errors: {
message: string;
start: [number, number];
end: [number, number];
}[] = JSON.parse(cargo.stdout);

errors.forEach((error) => {
diagnostics.push({
severity: 1,
range: {
start: { line: error.start[0], character: error.start[1] },
end: { line: error.end[0], character: error.end[1] },
},
message: error.message,
source: "ex",
});
});
});
} catch (err) {
console.log(err);
}
}

connection.sendDiagnostics({ uri: change.document.uri, diagnostics });
Expand Down
13 changes: 13 additions & 0 deletions quartz/ast.qz
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ enum Decl {
module_: Module,
},
t_import: Path,
t_attribute: LAttribute,
t_skip: bool,
}

module Decl {
Expand Down Expand Up @@ -153,6 +155,7 @@ enum Statement {
},
t_continue: bool,
t_break: bool,
t_attribute: LAttribute,
}

module Statement {
Expand Down Expand Up @@ -513,3 +516,13 @@ struct LPattern {
location: Location,
}

struct Attribute {
name: Ident,
args: vec[LExpression],
}

struct LAttribute {
data: Attribute,
location: Location,
}

49 changes: 37 additions & 12 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 @@ -17,19 +18,21 @@ struct LoadedModule {

struct Compiler {
loaded: vec[LoadedModule],
version: string,
}

module Compiler {
fun new(): Compiler {
fun new(version: string): Compiler {
return Compiler {
loaded: make[vec[LoadedModule]](),
version: version,
};
}

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 +45,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: self.version,
},
).try;
}

self.loaded.push(LoadedModule {
path: path,
source: input,
Expand All @@ -58,12 +77,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 +100,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 +132,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 +190,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 +289,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 +311,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 +337,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
39 changes: 36 additions & 3 deletions quartz/formatter.qz
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,47 @@ module Formatter {
}

fun decls(self, writer: stringbuilder, decls: vec[LDecl]) {
let prev = decls.at(0).data;
for i in 0..decls.length {
let decl = decls.at(i);

if decl.location.start != nil {
self.restore_comments(decl.location.start!, writer);
}
self.decl(writer, decl);
self.newline(writer);
if i != decls.length - 1 {
if prev.t_attribute != nil {
self.attribute(writer, prev.t_attribute!);
self.newline(writer);
}
if decl.data.t_attribute == nil {
self.decl(writer, decl);
self.newline(writer);
if i != decls.length - 1 {
self.newline(writer);
}
}

prev = decl.data;
}
}

fun attribute(self, writer: stringbuilder, lattr: LAttribute) {
let attr = lattr.data;

self.write(writer, "@");
self.write_no_space(writer, "[");
self.write_no_space(writer, attr.name.data);
if attr.args.length > 0 {
self.write_no_space(writer, "(");
for i in 0..attr.args.length {
let arg = attr.args.at(i);
self.expr(writer, arg, true);
if i != attr.args.length - 1 {
self.write(writer, ",");
}
}
self.write_no_space(writer, ")");
}
self.write_no_space(writer, "]");
}

fun decl(self, writer: stringbuilder, decl: LDecl) {
Expand Down Expand Up @@ -130,6 +159,8 @@ module Formatter {
self.write(writer, "import");
self.write(writer, d.t_import!.join("::"));
self.write_no_space(writer, ";");
} else if d.t_attribute != nil {
return;
}
}

Expand Down Expand Up @@ -423,6 +454,8 @@ module Formatter {
self.write(writer, "continue;");
} else if statement.t_break != nil {
self.write(writer, "break;");
} else if statement.t_attribute != nil {
self.attribute(writer, statement.t_attribute!);
}
}

Expand Down
7 changes: 6 additions & 1 deletion quartz/ir_code_gen.qz
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,12 @@ module IrCodeGenerator {
let elements = make[vec[IrTerm]]();

for i in 0..b.data.block.length {
elements.push(self.statement(b.data.block.at(i)).try);
let stm = b.data.block.at(i);
if stm.data.t_attribute != nil {
continue;
}

elements.push(self.statement(stm).try);
}

return elements;
Expand Down
3 changes: 3 additions & 0 deletions quartz/lexer.qz
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,9 @@ module Lexer {
if self.match(input, "&", "bit_and") {
continue;
}
if self.match(input, "@", "at") {
continue;
}

let number = self.consume_number(input);
if number != nil {
Expand Down
Loading