-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
229 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this | ||
// source code is governed by an MIT license that can be found in the LICENSE | ||
// file. | ||
|
||
import ../token; | ||
|
||
#[boxed] | ||
pub struct ImportedSymbol { | ||
pub name: string; | ||
pub sym: Sym; | ||
pub pos: token.Pos; | ||
pub mut is_used: bool; | ||
} | ||
|
||
pub struct ImportedSymbols { | ||
pub mut syms: []ImportedSymbol; | ||
|
||
#[inline] | ||
pub func add(mut self, name: string, sym: Sym, pos: token.Pos, is_used: bool := false) { | ||
self.syms.push(ImportedSymbol(name, sym, pos, is_used)); | ||
} | ||
|
||
pub func find(&self, name: string) -> ?ImportedSymbol { | ||
for imported_sym in self.syms { | ||
if name == imported_sym.name { | ||
return imported_sym; | ||
} | ||
} | ||
return none; | ||
} | ||
|
||
#[inline] | ||
pub func exists(&self, name: string) -> bool { | ||
return self.find(name) != none; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this | ||
// source code is governed by an MIT license that can be found in the LICENSE | ||
// file. | ||
|
||
import std/traits.Stringable; | ||
|
||
import ../token; | ||
|
||
#[boxed] | ||
pub enum Node < Stringable { | ||
Decl(Decl), | ||
Stmt(Stmt), | ||
Expr(Expr); | ||
|
||
pub func position(self) -> token.Pos { | ||
return match self { | ||
.Decl(decl) -> decl.position(), | ||
.Stmt(stmt) -> stmt.position(), | ||
.Expr(expr) -> expr.position() | ||
}; | ||
} | ||
|
||
pub func to_string(self) -> string { | ||
return match self { | ||
/*.Decl(decl) -> decl.to_string(), | ||
.Stmt(stmt) -> stmt.to_string(),*/ | ||
.Expr(expr) -> expr.to_string(), | ||
else -> "<not-implemented>" | ||
}; | ||
} | ||
} | ||
pub func nodes_to_decls(nodes: []mut Node) -> []mut Decl { | ||
mut decls := []mut Decl(); | ||
for node in nodes { | ||
if node is .Decl(decl) { | ||
decls.push(decl); | ||
} | ||
} | ||
return decls; | ||
} | ||
pub func nodes_to_stmts(nodes: []mut Node) -> []mut Stmt { | ||
mut stmts := []mut Stmt(); | ||
for node in nodes { | ||
if node is .Stmt(stmt) { | ||
stmts.push(stmt); | ||
} | ||
} | ||
return stmts; | ||
} | ||
pub func nodes_to_exprs(nodes: []mut Node) -> []mut Expr { | ||
mut exprs := []mut Expr(); | ||
for node in nodes { | ||
if node is .Expr(expr) { | ||
exprs.push(expr); | ||
} | ||
} | ||
return exprs; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this | ||
// source code is governed by an MIT license that can be found in the LICENSE | ||
// file. | ||
|
||
import ../token; | ||
import ../report; | ||
|
||
pub struct ComptimeIf { | ||
mut branches: []mut ComptimeIfBranch; | ||
mut branch_idx: ?uint; | ||
has_else: bool; | ||
pos: token.Pos; | ||
mut type: Type; | ||
|
||
pub func nodes(self) -> ?[]Node { | ||
if branch_idx := self.branch_idx { | ||
return self.branches[branch_idx].nodes; | ||
} | ||
return none; | ||
} | ||
} | ||
|
||
pub struct ComptimeIfBranch { | ||
pub mut cond: Expr; | ||
pub is_else: bool; | ||
pub is_else_if: bool; | ||
pub mut nodes: []mut Node; | ||
pub pos: token.Pos; | ||
pub mut type: Type; | ||
} | ||
|
||
extend Env { | ||
pub func evalue_comptime_if(self, mut comptime_if: ComptimeIf) -> []mut Node { | ||
for i, branch in comptime_if.branches { | ||
if branch.is_else && comptime_if.branch_idx == none { | ||
comptime_if.branch_idx = i; | ||
} else if cond := self.evalue_comptime_condition(branch.cond); cond { | ||
comptime_if.branch_idx = i; | ||
} | ||
if branch_idx := comptime_if.branch_idx { | ||
return comptime_if.branches[branch_idx].nodes; | ||
} | ||
} | ||
return +[]; | ||
} | ||
|
||
func evalue_comptime_condition(self, cond: Expr) -> ?bool { | ||
return match cond { | ||
else -> { | ||
report.error("invalid comptime condition", cond.position()); | ||
none | ||
} | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this | ||
// source code is governed by an MIT license that can be found in the LICENSE | ||
// file. | ||
|
||
import ../ast; | ||
import ../report; | ||
|
||
extend Parser { | ||
enum ComptimeLevel as uint8 { | ||
Decl, | ||
Stmt, | ||
Expr | ||
} | ||
|
||
func parse_nodes(mut self, level: ComptimeLevel) -> []mut ast.Node { | ||
return match level { | ||
.Decl -> { | ||
mut decls := []mut ast.Node(); | ||
if self.accept(.Lbrace) { | ||
while self.tok.kind != .Rbrace { | ||
decls.push(.Decl(self.parse_decl())) | ||
} | ||
self.expect(.Rbrace); | ||
} else { | ||
decls.push(.Decl(self.parse_decl())) | ||
} | ||
decls | ||
}, | ||
.Stmt -> { | ||
mut stmts := []mut ast.Node(); | ||
if self.accept(.Lbrace) { | ||
while self.tok.kind != .Rbrace { | ||
stmts.push(.Stmt(self.parse_stmt())); | ||
} | ||
self.expect(.Rbrace); | ||
} else { | ||
stmts.push(.Stmt(self.parse_stmt())); | ||
} | ||
stmts | ||
}, | ||
.Expr -> +[.Expr(self.parse_expr())] | ||
}; | ||
} | ||
|
||
func parse_comptime_if(mut self, level: ComptimeLevel) -> ast.ComptimeIf { | ||
mut branches := []mut ast.ComptimeIfBranch(); | ||
mut has_else := false; | ||
mut pos := self.tok.pos; | ||
while self.tok.kind in [.KwIf, .KwElse] { | ||
branch_pos := self.tok.pos; | ||
if self.accept(.KwElse) && self.tok.kind != .KwIf { | ||
branches.push( | ||
ast.ComptimeIfBranch( | ||
.Empty(self.tok.pos), nodes: self.parse_nodes(level), | ||
is_else: true, pos: branch_pos + self.prev_tok.pos | ||
) | ||
); | ||
has_else = true; | ||
break; | ||
} | ||
is_else_if := self.prev_tok.kind == .KwElse; | ||
self.expect(.KwIf); | ||
cond := self.parse_expr(); | ||
branches.push( | ||
ast.ComptimeIfBranch( | ||
cond, nodes: self.parse_nodes(level), is_else_if: is_else_if, | ||
pos: branch_pos + self.prev_tok.pos | ||
) | ||
); | ||
if self.tok.kind != .KwElse { | ||
break; | ||
} | ||
} | ||
pos += self.prev_tok.pos; | ||
return ast.ComptimeIf(branches, has_else: has_else, pos: pos); | ||
} | ||
} |