Skip to content

Commit

Permalink
feat(types): inference
Browse files Browse the repository at this point in the history
  • Loading branch information
megatank58 committed May 5, 2023
1 parent f846da1 commit cfadc8b
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 19 deletions.
2 changes: 1 addition & 1 deletion examples/echo.oxi
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
let a: str = read();
let a = read();

println(a);
6 changes: 3 additions & 3 deletions examples/factorial.oxi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
let s: str = "10";
let s = "10";

let n: int = int(s);
let n = int(s);

fn factorial(n: int) -> int {
if n == 0 {
Expand All @@ -10,6 +10,6 @@ fn factorial(n: int) -> int {
return n * factorial(n - 1);
}

let f: int = factorial(n);
let f = factorial(n);

println(f);
2 changes: 1 addition & 1 deletion examples/function.oxi
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ fn add(a: int, b: int) -> int {
return a + b;
}

let c: int = add(5, 3) + 2;
let c = add(5, 3) + 2;

println(c);
4 changes: 2 additions & 2 deletions examples/pattern.oxi
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
let i: int = 1;
let j: int = 1;
let i = 1;
let j = 1;

loop {
if i > 5 {
Expand Down
2 changes: 1 addition & 1 deletion src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub type Ast = Vec<(AstNode, Range<usize>)>;

#[derive(Clone, Debug)]
pub enum AstNode {
Assignment(String, DataType, Expression),
Assignment(String, Option<DataType>, Expression),
ReAssignment(String, Expression),
If(Expression, Ast),
Loop(Ast),
Expand Down
19 changes: 19 additions & 0 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ impl<'a> Interpreter<'a> {
match node.0 {
AstNode::Assignment(ident, datatype, expression) => {
let data = self.parse_expression(expression, &node.1);
let datatype = if datatype.is_none() {
data.r#type()
} else {
datatype.unwrap()
};
if datatype != data.r#type() {
error(
self.name,
self.file,
"E00011",
"incorrect data type",
&format!(
"mismatched data types expected {} found {}",
datatype,
data.to_string()
),
&node.1,
)
}
self.variables.insert(ident, Variable::new(datatype, data));
}
AstNode::ReAssignment(ident, expression) => {
Expand Down
55 changes: 44 additions & 11 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{iter::Peekable, ops::Range, vec::IntoIter};

use crate::{
ast::{Ast, AstNode, Expression},
data::Param,
data::{DataType, Param},
error::error,
token::{Token, Tokens},
};
Expand Down Expand Up @@ -193,18 +193,12 @@ impl<'a> Parser<'a> {
let node: (AstNode, Range<usize>) = if token.0 == Token::Let {
let t = &stream.next()?;
if let Token::Identifier(ident) = &t.0 {
let t = stream.next()?;
let t = stream.peek()?;
let datatype = if let Token::DataType(datatype) = t.0 {
datatype
stream.next()?;
Some(datatype)
} else {
error(
self.name,
self.file,
"E0010",
"expected data type",
"expected data type",
&(t.1 - 1..t.1 + t.0.len() - 1),
)
None
};

self.check(stream.next()?, Token::Equal);
Expand All @@ -219,6 +213,16 @@ impl<'a> Parser<'a> {

let (expression, _) = self.pratt_parser(tokens.into_iter().peekable(), 0);

println!("{datatype:?}");

let datatype = if datatype.is_none() {
let datatype = self.infer_datatype(&expression);

datatype
} else {
datatype
};

(
AstNode::Assignment(ident.to_string(), datatype, expression),
token.1..t.1,
Expand Down Expand Up @@ -478,6 +482,35 @@ impl<'a> Parser<'a> {
true
}

pub fn infer_datatype(&self, expr: &Expression) -> Option<DataType> {
match expr {
Expression::BinaryOperation(lhs, _, rhs) => {
let lhs = self.infer_datatype(lhs);
let rhs = self.infer_datatype(rhs);

if lhs.is_none() || rhs.is_none() {
return None;
};

let lhs = lhs.unwrap();
let rhs = rhs.unwrap();

Some(match (lhs, rhs) {
(DataType::Str, _) => DataType::Str,
(_, DataType::Str) => DataType::Str,
(DataType::Int, _) => DataType::Int,
(_, DataType::Int) => DataType::Int,
(DataType::Bool, _) => DataType::Bool,
})
}
Expression::Str(_) => Some(DataType::Str),
Expression::Int(_) => Some(DataType::Int),
Expression::Bool(_) => Some(DataType::Bool),
Expression::FunctionCall(_, _) => None,
Expression::Identifier(_) => None,
}
}

pub fn pratt_parser(
&'a self,
mut lexer: Peekable<IntoIter<&'a (Token, usize)>>,
Expand Down

0 comments on commit cfadc8b

Please sign in to comment.