Browse Source

Add types to function arguments

github-actions
Garrit Franke 2 years ago
parent
commit
a565849f3a
  1. 2
      examples/ackermann.sb
  2. 2
      examples/fib.sb
  3. 2
      examples/greeter.sb
  4. 8
      lib/stdio.sb
  5. 1
      src/main.rs
  6. 21
      src/parser/node_type.rs
  7. 28
      src/parser/rules.rs
  8. 32
      src/parser/tests.rs

2
examples/ackermann.sb

@ -4,7 +4,7 @@ fn main() {
println(ackermann(m, n))
}
fn ackermann(m, n) {
fn ackermann(m int, n int) {
if m == 0 {
return n + 1
} else if n == 0 {

2
examples/fib.sb

@ -3,7 +3,7 @@ fn main() {
println(fib(num))
}
fn fib(n) {
fn fib(n int) {
if 1 >= n {
return n
}

2
examples/greeter.sb

@ -2,6 +2,6 @@ fn main() {
println(greet("World"))
}
fn greet(name) {
fn greet(name string) {
return "Hello " + name
}

8
lib/stdio.sb

@ -1,16 +1,16 @@
// Raw wrapper around _printf builtin function.
// Writes the given content to stdout
fn print(msg) {
fn print(msg string) {
_printf(msg)
}
// Like print(), but with an extra newline ('\n') character
fn println(msg) {
fn println(msg string) {
print(msg + "\n")
}
// Prints the size of an array
fn len(arr) {
fn len(arr int[]) {
let c = 0
while arr[c] {
c = c + 1
@ -21,7 +21,7 @@ fn len(arr) {
// Reverses an array
// TODO: fix me!
fn rev(arr) {
fn rev(arr int[]) {
let l = len(arr)
let new_arr = []

1
src/main.rs

@ -67,6 +67,7 @@ fn main() -> Result<(), String> {
let tokens = lexer::tokenize(&contents);
let program = parser::parse(tokens, Some(contents))?;
dbg!(&program);
let output = generator::js::JsGenerator::generate(program);
let mut file = std::fs::File::create(out_file).expect("create failed");

21
src/parser/node_type.rs

@ -32,6 +32,27 @@ pub struct Function {
#[derive(Debug, Eq, PartialEq)]
pub struct Variable {
pub name: String,
pub ty: Option<Type>,
}
#[derive(Debug, Eq, PartialEq)]
pub enum Type {
Int,
Str,
Bool,
Array(Box<Type>),
}
impl TryFrom<String> for Type {
type Error = String;
fn try_from(s: String) -> Result<Self, Self::Error> {
match s.as_ref() {
"int" => Ok(Self::Int),
"string" => Ok(Self::Str),
"bool" => Ok(Self::Bool),
_ => Err("Expected Type".into()),
}
}
}
#[derive(Debug, Eq, PartialEq)]

28
src/parser/rules.rs

@ -58,9 +58,7 @@ impl Parser {
let arguments: Vec<Variable> = match self.peek()? {
t if t.kind == TokenKind::BraceClose => Vec::new(),
_ => self
.parse_arguments()
.expect("Failed to parse function arguments"),
_ => self.parse_arguments()?,
};
self.match_token(TokenKind::BraceClose)?;
@ -82,7 +80,10 @@ impl Parser {
TokenKind::Comma => {
continue;
}
TokenKind::Identifier(name) => args.push(Variable { name: name }),
TokenKind::Identifier(name) => args.push(Variable {
name: name,
ty: Some(self.parse_type()?),
}),
_ => return Err(self.make_error(TokenKind::Identifier("Argument".into()), next)),
}
}
@ -90,6 +91,21 @@ impl Parser {
Ok(args)
}
fn parse_type(&mut self) -> Result<Type, String> {
let next = self.next()?;
let typ = match next.kind {
TokenKind::Identifier(t) => Type::try_from(t),
_ => Err("Expected type".into()),
}?;
if let Ok(_) = self.peek_token(TokenKind::SquareBraceOpen) {
self.drop(1);
self.match_token(TokenKind::SquareBraceClose)?;
Ok(Type::Array(Box::new(typ)))
} else {
Ok(typ)
}
}
fn parse_statement(&mut self) -> Result<Statement, String> {
let token = self.peek()?;
let state = match &token.kind {
@ -333,12 +349,12 @@ impl Parser {
self.match_keyword(Keyword::Let)?;
match (self.next()?.kind, self.peek()?.kind) {
(TokenKind::Identifier(name), TokenKind::SemiColon) => {
Ok(Statement::Declare(Variable { name }, None))
Ok(Statement::Declare(Variable { name, ty: None }, None))
}
(TokenKind::Identifier(name), TokenKind::Assign) => {
self.drop(1);
let exp = self.parse_expression().ok();
Ok(Statement::Declare(Variable { name }, exp))
Ok(Statement::Declare(Variable { name, ty: None }, exp))
}
other => Err(format!("Expected identifier, found {:?}", other)),
}

32
src/parser/tests.rs

@ -120,7 +120,7 @@ fn test_parse_variable_declaration_added() {
#[test]
fn test_parse_function_with_args() {
let raw = "
fn main(foo) {
fn main(foo int) {
return foo
}
";
@ -132,7 +132,7 @@ fn test_parse_function_with_args() {
#[test]
fn test_parse_function_call() {
let raw = "
fn main(foo) {
fn main(foo int) {
foo()
}
@ -184,7 +184,7 @@ fn test_parse_nexted_function_call() {
fib(fib(2), 2)
}
fn fib(n) {
fn fib(n int) {
return 2
}
";
@ -244,7 +244,7 @@ fn test_parse_compound_ops_with_strings() {
#[test]
fn test_parse_compound_ops_with_identifier() {
let raw = "
fn main(n) {
fn main(n int) {
return 2 * n
}
";
@ -256,7 +256,7 @@ fn test_parse_compound_ops_with_identifier() {
#[test]
fn test_parse_compound_ops_with_identifier_first() {
let raw = "
fn main(n) {
fn main(n int) {
return n * 2
}
";
@ -268,7 +268,7 @@ fn test_parse_compound_ops_with_identifier_first() {
#[test]
fn test_parse_compound_ops_return() {
let raw = "
fn main(n) {
fn main(n int) {
return 2 * n
}
";
@ -280,7 +280,7 @@ fn test_parse_compound_ops_return() {
#[test]
fn test_parse_basic_conditional() {
let raw = "
fn main(n) {
fn main(n int) {
if n {
return n
}
@ -294,7 +294,7 @@ fn test_parse_basic_conditional() {
#[test]
fn test_parse_basic_conditional_with_multiple_statements() {
let raw = "
fn main(n) {
fn main(n int) {
if n {
let x = 2 * n
return x
@ -309,7 +309,7 @@ fn test_parse_basic_conditional_with_multiple_statements() {
#[test]
fn test_parse_conditional_else_if_branch() {
let raw = "
fn main(n) {
fn main(n int) {
if n > 10 {
let x = 2 * n
return x
@ -326,7 +326,7 @@ fn test_parse_conditional_else_if_branch() {
#[test]
fn test_parse_conditional_multiple_else_if_branch_branches() {
let raw = "
fn main(n) {
fn main(n int) {
if n > 10 {
let x = 2 * n
return x
@ -345,7 +345,7 @@ fn test_parse_conditional_multiple_else_if_branch_branches() {
#[test]
fn test_parse_conditional_else_branch() {
let raw = "
fn main(n) {
fn main(n int) {
if n > 10 {
let x = 2 * n
return x
@ -362,7 +362,7 @@ fn test_parse_conditional_else_branch() {
#[test]
fn test_parse_conditional_elseif_else_branch() {
let raw = "
fn main(n) {
fn main(n int) {
if n > 10 {
let x = 2 * n
return x
@ -383,7 +383,7 @@ fn test_parse_conditional_elseif_else_branch() {
#[test]
fn test_int_array() {
let raw = "
fn main(n) {
fn main(n int) {
let arr = [1, 2, 3]
return arr
}
@ -396,7 +396,7 @@ fn test_int_array() {
#[test]
fn test_string_array() {
let raw = "
fn main(n) {
fn main(n int) {
return [\"Foo\", \"Bar\", \"Baz\"]
}
";
@ -533,7 +533,7 @@ fn test_uninitialized_variables() {
#[test]
fn test_function_call_math() {
let raw = "
fn main(m) {
fn main(m int) {
main(m - 1)
}
";
@ -545,7 +545,7 @@ fn test_function_call_math() {
#[test]
fn test_function_multiple_args() {
let raw = "
fn main(m, n) {
fn main(m int, n int) {
main(m, n)
}
";

Loading…
Cancel
Save