diff --git a/src/analyzer.rs b/src/analyzer.rs
index 7dbed93..7dae999 100644
--- a/src/analyzer.rs
+++ b/src/analyzer.rs
@@ -22,6 +22,7 @@ impl Analyzer {
params,
return_type: _,
body: _,
+ exported: _,
} = stmt
{
if self.functions.contains_key(&name.lexeme) {
@@ -65,6 +66,7 @@ impl Analyzer {
params: _,
return_type,
body,
+ exported: _,
} => {
if name.lexeme == "main" && return_type.lexeme != "I64" {
return error!(&name.loc, "main must return I64");
diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs
index 127437a..d92799e 100644
--- a/src/codegen_x86_64.rs
+++ b/src/codegen_x86_64.rs
@@ -232,8 +232,9 @@ _builtin_environ:
params,
return_type: _,
body,
+ exported,
} => {
- if name.lexeme == "main" {
+ if exported || name.lexeme == "main" {
emit!(&mut self.output, "global {}", name.lexeme);
}
emit!(&mut self.output, "section .text.{}", name.lexeme);
diff --git a/src/parser.rs b/src/parser.rs
index 16f7017..d90ad45 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -35,6 +35,7 @@ pub enum Stmt {
params: Vec,
return_type: Token,
body: Box,
+ exported: bool,
},
Return(Expr),
Break,
@@ -101,7 +102,11 @@ impl Parser {
fn declaration(&mut self) -> Result {
if !self.is_inside_function {
if self.match_token(&[TokenType::KeywordFunc]) {
- return self.func_declaration();
+ return self.func_declaration(false);
+ }
+ if self.match_token(&[TokenType::KeywordExport]) {
+ self.consume(TokenType::KeywordFunc, "expected 'func' after 'export'")?;
+ return self.func_declaration(true);
}
if self.match_token(&[TokenType::KeywordExtern]) {
return self.extern_declaration();
@@ -119,7 +124,7 @@ impl Parser {
}
}
- fn func_declaration(&mut self) -> Result {
+ fn func_declaration(&mut self, exported: bool) -> Result {
let name = self.consume(TokenType::Identifier, "expected function name")?;
self.consume(TokenType::LeftBracket, "expected '[' after function name")?;
@@ -157,6 +162,7 @@ impl Parser {
params,
return_type,
body,
+ exported,
})
}
diff --git a/src/std.zr b/src/std.zr
index 9915e2e..ba1bb28 100644
--- a/src/std.zr
+++ b/src/std.zr
@@ -229,6 +229,12 @@ func str.from_i64[n: I64] : String
mem.free(buf)
return s
+func str.from_char[c: U8] : String
+ let s: String = mem.alloc(2)
+ str.set(s, 0, c)
+ str.set(s, 1, 0)
+ return s
+
func str.parse_i64[s: String] : I64
let len: I64 = str.len(s)
let i: I64 = 0
diff --git a/src/tokenizer.rs b/src/tokenizer.rs
index cdf00d8..f781f37 100644
--- a/src/tokenizer.rs
+++ b/src/tokenizer.rs
@@ -48,6 +48,7 @@ pub enum TokenType {
KeywordBreak,
KeywordContinue,
KeywordExtern,
+ KeywordExport,
Indent,
Dedent,
@@ -340,6 +341,7 @@ impl Tokenizer {
"break" => TokenType::KeywordBreak,
"continue" => TokenType::KeywordContinue,
"extern" => TokenType::KeywordExtern,
+ "export" => TokenType::KeywordExport,
"true" => TokenType::True,
"false" => TokenType::False,
_ => TokenType::Identifier,