function return type added
This commit is contained in:
parent
a9b150a40e
commit
6e5461ce33
14
src/main.rs
14
src/main.rs
|
@ -18,17 +18,19 @@ fn main() {
|
|||
|
||||
let source =
|
||||
r"
|
||||
pi = 3.1415926535
|
||||
#pi = 3.1415926535
|
||||
|
||||
foo(x:i4, y:f4) {
|
||||
foo(x :int, y: rat) = bool {
|
||||
|
||||
}
|
||||
|
||||
main() {
|
||||
a:i4 = 8
|
||||
b:f4 = 9
|
||||
main {
|
||||
unless 3 > 4 {
|
||||
a = 4 + 5;
|
||||
b = 0.3 + 7;
|
||||
|
||||
foo(a, 6)
|
||||
foo(a, b)
|
||||
}
|
||||
}
|
||||
";
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ pub struct Declr<'a> {
|
|||
pub args: Option<Vec<(&'a str, Prim)>>,
|
||||
/// if the function returns a single value
|
||||
pub results: bool,
|
||||
/// type of result
|
||||
pub result_typ: Option<Prim>
|
||||
}
|
||||
|
||||
impl<'a> Declr<'a> {
|
||||
|
@ -35,7 +37,8 @@ impl<'a> Declr<'a> {
|
|||
Self {
|
||||
name: None,
|
||||
args: None,
|
||||
results: false
|
||||
results: false,
|
||||
result_typ: None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,11 +22,16 @@ fn discover_functions<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &str)
|
|||
let mut single_line = false;
|
||||
|
||||
macro_rules! finish_func {
|
||||
() => {
|
||||
($dbginf:expr) => {
|
||||
if declrs.contains(&declr) {
|
||||
panic!("Function defined multiple times: {declr}")
|
||||
}
|
||||
|
||||
if declr.results && declr.result_typ.is_none() {
|
||||
$dbginf.print(MessageType::Error, format!("Function is missing return type: {}", declr).as_str(), source);
|
||||
panic!();
|
||||
}
|
||||
|
||||
funcs.push(func);
|
||||
declrs.push(declr);
|
||||
declr = Declr::new();
|
||||
|
@ -62,15 +67,25 @@ fn discover_functions<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &str)
|
|||
'}' => {
|
||||
brace_cnt -= 1;
|
||||
if brace_cnt == 0 {
|
||||
finish_func!();
|
||||
finish_func!(dbginf);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
Token::LineBreak(_) => if single_line {
|
||||
finish_func!();
|
||||
Token::Type(typ, dbginf) => {
|
||||
if declr.results {
|
||||
declr.result_typ = Some(*typ);
|
||||
continue;
|
||||
} else {
|
||||
dbginf.print(MessageType::Error, "Missing equal sign", source);
|
||||
panic!();
|
||||
}
|
||||
},
|
||||
|
||||
Token::LineBreak(dbginf) => if single_line {
|
||||
finish_func!(dbginf);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -99,6 +114,23 @@ fn discover_functions<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &str)
|
|||
_ => ()
|
||||
}
|
||||
|
||||
Token::Word(text, dbginf) => {
|
||||
|
||||
if declr.name.is_some() {
|
||||
if declr.args.is_none() {
|
||||
dbginf.print(MessageType::Error, "multiple function names", source);
|
||||
panic!();
|
||||
}
|
||||
} else if brace_cnt > 0 {
|
||||
dbginf.print(MessageType::Error, "brace count missmatch", source);
|
||||
panic!();
|
||||
}
|
||||
else {
|
||||
declr.name = Some(text);
|
||||
continue;
|
||||
}
|
||||
},
|
||||
|
||||
Token::Assign(name, _, dbginf) => {
|
||||
if declr.results {
|
||||
dbginf.print(MessageType::Error, "double function assignment", source);
|
||||
|
@ -139,23 +171,6 @@ fn discover_functions<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &str)
|
|||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
Token::Word(text, dbginf) => {
|
||||
|
||||
if declr.name.is_some() {
|
||||
if declr.args.is_none() {
|
||||
dbginf.print(MessageType::Error, "multiple function names", source);
|
||||
panic!();
|
||||
}
|
||||
} else if brace_cnt > 0 {
|
||||
dbginf.print(MessageType::Error, "brace count missmatch", source);
|
||||
panic!();
|
||||
}
|
||||
else {
|
||||
declr.name = Some(text);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
@ -298,7 +313,7 @@ fn check_var_typ(typ: &mut Option<Prim>, operands: &mut Vec<Prim>, dbginf: &crat
|
|||
|
||||
fn process_keyword(keyword: Keyword, _: &Vec<Declr>, _: &mut Scope, operands: &mut Vec<Prim>, dbginf: &crate::token::DebugInfo, source: &str) {
|
||||
match keyword {
|
||||
Keyword::If => {
|
||||
Keyword::If | Keyword::While => {
|
||||
if operands.len() != 1 {
|
||||
dbginf.print(MessageType::Error, format!("Expected single boolean got {} values", operands.len()).as_str(), source);
|
||||
panic!();
|
||||
|
@ -331,7 +346,7 @@ fn collapse_operation(operation: &Token, declrs: &Vec<Declr>, scope: &mut Scope,
|
|||
}
|
||||
}
|
||||
|
||||
fn call_func(name: &str, declrs: &Vec<Declr>, scope: &mut Scope, operands: &mut Vec<Prim>, dbginf: &crate::token::DebugInfo, source: &str) {
|
||||
fn call_func(name: &str, declrs: &Vec<Declr>, _: &mut Scope, operands: &mut Vec<Prim>, dbginf: &crate::token::DebugInfo, source: &str) {
|
||||
for declr in declrs {
|
||||
if declr.name.is_some() && declr.name.unwrap() == name {
|
||||
|
||||
|
@ -391,9 +406,9 @@ fn parse_term<'a>(term: &mut VecDeque<Token<'a>>, declrs: &Vec<Declr<'a>>, scope
|
|||
output.push_back(token);
|
||||
value_stack.push(Prim::Bool)
|
||||
},
|
||||
Token::Number(_, _) => {
|
||||
Token::Number(_, hint, _) => {
|
||||
output.push_back(token);
|
||||
value_stack.push(Prim::UntypedNum)
|
||||
value_stack.push(Prim::UntypedNum(*hint))
|
||||
},
|
||||
Token::Assign(_, _, _) => {
|
||||
op_stack.push(token);
|
||||
|
@ -521,7 +536,9 @@ pub fn parse<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &'a str) -> Ve
|
|||
discover_exprs(&mut funcs, &declrs, source);
|
||||
parse_exprs(&mut funcs, &declrs, source);
|
||||
|
||||
funcs.iter().for_each(|f| println!("{:?}", f));
|
||||
for (x, f) in funcs.iter().enumerate() {
|
||||
println!("{:?}{:?}", declrs[x], f);
|
||||
}
|
||||
|
||||
funcs
|
||||
}
|
113
src/token/mod.rs
113
src/token/mod.rs
|
@ -108,16 +108,21 @@ impl Operator {
|
|||
match self {
|
||||
Operator::Add | Operator::Sub | Operator::Mul | Operator::Div=> {
|
||||
let types_valid = Self::check_types(operands, &[
|
||||
// +-----------------------------------+---------------------------------+
|
||||
// | Parameter list of types | result type |
|
||||
// +-----------------------------------+---------------------------------+
|
||||
(vec![Prim::Int, Prim::Int ], Prim::Int ),
|
||||
(vec![Prim::Real, Prim::Real ], Prim::Real),
|
||||
(vec![Prim::UntypedNum, Prim::Int ], Prim::Int ),
|
||||
(vec![Prim::UntypedNum, Prim::Real ], Prim::Real),
|
||||
(vec![Prim::Int, Prim::UntypedNum], Prim::Int ),
|
||||
(vec![Prim::Real, Prim::UntypedNum], Prim::Real),
|
||||
(vec![Prim::UntypedNum, Prim::UntypedNum], Prim::UntypedNum)
|
||||
// +-------------------------------------------------------------------------------+---------------------------------+
|
||||
// | Parameter list of types | result type |
|
||||
// +-------------------------------------------------------------------------------+---------------------------------+
|
||||
(vec![Prim::Int, Prim::Int ], Prim::Int),
|
||||
(vec![Prim::Rat, Prim::Rat ], Prim::Rat),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::Int ], Prim::Int),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::Rat ], Prim::Rat),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Rat), Prim::Rat ], Prim::Rat),
|
||||
(vec![Prim::Int, Prim::UntypedNum(NumberClassHint::Int)], Prim::Int),
|
||||
(vec![Prim::Rat, Prim::UntypedNum(NumberClassHint::Rat)], Prim::Rat),
|
||||
(vec![Prim::Rat, Prim::UntypedNum(NumberClassHint::Int)], Prim::Rat),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Rat), Prim::UntypedNum(NumberClassHint::Rat)], Prim::Rat),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::UntypedNum(NumberClassHint::Rat)], Prim::Rat),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Rat), Prim::UntypedNum(NumberClassHint::Int)], Prim::Rat),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::UntypedNum(NumberClassHint::Int)], Prim::Int)
|
||||
], dbginf, source);
|
||||
|
||||
if let Some(result) = types_valid {
|
||||
|
@ -125,7 +130,7 @@ impl Operator {
|
|||
operands.pop();
|
||||
operands.push(result);
|
||||
} else {
|
||||
dbginf.print(MessageType::Error, format!("Missmatched types for {:?}, expected either two integer or reals", self).as_str(), source);
|
||||
dbginf.print(MessageType::Error, format!("Missmatched types for {:?}, expected either two integer or rationals", self).as_str(), source);
|
||||
panic!()
|
||||
}
|
||||
},
|
||||
|
@ -145,17 +150,20 @@ impl Operator {
|
|||
},
|
||||
Operator::Eq | Operator::NotEq | Operator::Lt | Operator::Gt | Operator::GtEq | Operator::LtEq => {
|
||||
let types_valid = Self::check_types(operands, &[
|
||||
(vec![Prim::Int, Prim::Int ], Prim::Bool ),
|
||||
(vec![Prim::Real, Prim::Real ], Prim::Bool ),
|
||||
(vec![Prim::UntypedNum, Prim::Int ], Prim::Bool ),
|
||||
(vec![Prim::UntypedNum, Prim::Real ], Prim::Bool ),
|
||||
(vec![Prim::Int, Prim::UntypedNum], Prim::Bool ),
|
||||
(vec![Prim::Real, Prim::UntypedNum], Prim::Bool ),
|
||||
(vec![Prim::UntypedNum, Prim::UntypedNum], Prim::Bool )
|
||||
// +-------------------------------------------------------------------------------+---------------------------------+
|
||||
// | Parameter list of types | result type |
|
||||
// +-------------------------------------------------------------------------------+---------------------------------+
|
||||
(vec![Prim::Int, Prim::Int ], Prim::Bool ),
|
||||
(vec![Prim::Rat, Prim::Rat ], Prim::Bool ),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::Int ], Prim::Bool ),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Rat), Prim::Rat ], Prim::Bool ),
|
||||
(vec![Prim::Int, Prim::UntypedNum(NumberClassHint::Int)], Prim::Bool ),
|
||||
(vec![Prim::Rat, Prim::UntypedNum(NumberClassHint::Rat)], Prim::Bool ),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Rat), Prim::UntypedNum(NumberClassHint::Rat)], Prim::Bool ),
|
||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::UntypedNum(NumberClassHint::Int)], Prim::Bool )
|
||||
], dbginf, source);
|
||||
|
||||
if let Some(result) = types_valid {
|
||||
println!("checked: {:?} for: {:?}", self, operands);
|
||||
|
||||
operands.pop();
|
||||
operands.pop();
|
||||
|
@ -193,20 +201,37 @@ impl Keyword {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
|
||||
pub enum NumberClassHint {
|
||||
Int,
|
||||
Rat
|
||||
}
|
||||
|
||||
impl NumberClassHint {
|
||||
|
||||
pub fn from(str: &str) -> NumberClassHint {
|
||||
if str.parse::<i32>().is_err() {
|
||||
return NumberClassHint::Rat;
|
||||
}
|
||||
|
||||
NumberClassHint::Int
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
|
||||
/// primitve types
|
||||
pub enum Prim {
|
||||
Int,
|
||||
Real,
|
||||
Rat,
|
||||
Bool,
|
||||
UntypedNum
|
||||
UntypedNum(NumberClassHint)
|
||||
}
|
||||
|
||||
impl Prim {
|
||||
fn from<'a>(text: &'a str, dbginf: &DebugInfo, source: &str) -> Prim {
|
||||
return match text {
|
||||
"i4" => Prim::Int,
|
||||
"f4" => Prim::Real,
|
||||
"int" => Prim::Int,
|
||||
"rat" => Prim::Rat,
|
||||
"bool" => Prim::Bool,
|
||||
|
||||
_ => {
|
||||
|
@ -219,16 +244,21 @@ impl Prim {
|
|||
pub fn is_equal(&self, value: Prim) -> bool {
|
||||
return match self {
|
||||
Prim::Bool => *self == value,
|
||||
Prim::Real => return match value {
|
||||
Prim::UntypedNum => true,
|
||||
Prim::Rat => return match value {
|
||||
Prim::UntypedNum(NumberClassHint::Int) => true,
|
||||
Prim::UntypedNum(NumberClassHint::Rat) => true,
|
||||
_ => *self == value,
|
||||
},
|
||||
Prim::Int => return match value {
|
||||
Prim::UntypedNum => true,
|
||||
Prim::UntypedNum(NumberClassHint::Int) => true,
|
||||
_ => *self == value,
|
||||
},
|
||||
Prim::UntypedNum => return match value {
|
||||
Prim::Real | Prim::Int => true,
|
||||
Prim::UntypedNum(NumberClassHint::Rat) => return match value {
|
||||
Prim::Rat | Prim::Int => true,
|
||||
_ => *self == value,
|
||||
},
|
||||
Prim::UntypedNum(NumberClassHint::Int) => return match value {
|
||||
Prim::Int => true,
|
||||
_ => *self == value,
|
||||
},
|
||||
}
|
||||
|
@ -289,7 +319,7 @@ pub enum Token<'a> {
|
|||
/// Single symbol delemiter like ```(```,```}```
|
||||
Delemiter(char, DebugInfo),
|
||||
Operator(Operator, DebugInfo),
|
||||
Number(&'a str, DebugInfo),
|
||||
Number(&'a str, NumberClassHint, DebugInfo),
|
||||
LineBreak(DebugInfo),
|
||||
Func(&'a str, DebugInfo),
|
||||
/// Variable
|
||||
|
@ -303,16 +333,18 @@ pub enum Token<'a> {
|
|||
Bool(bool, DebugInfo),
|
||||
/// Keywords like ```if```,```break```,```while```
|
||||
Keyword(Keyword, DebugInfo),
|
||||
Type(Prim, DebugInfo)
|
||||
}
|
||||
|
||||
impl<'a> Token<'a> {
|
||||
/// redirect for ```DebugInfo.print()```
|
||||
pub fn print(&self, error: MessageType, arg: &str, source: &str) {
|
||||
match self {
|
||||
Token::Type(_, dbginf) => dbginf.print(error, arg, source),
|
||||
Token::Word(_, dbginf) => dbginf.print(error, arg, source),
|
||||
Token::Delemiter(_, dbginf) => dbginf.print(error, arg, source),
|
||||
Token::Operator(_, dbginf) => dbginf.print(error, arg, source),
|
||||
Token::Number(_, dbginf) => dbginf.print(error, arg, source),
|
||||
Token::Number(_, _, dbginf) => dbginf.print(error, arg, source),
|
||||
Token::LineBreak(dbginf) => dbginf.print(error, arg, source),
|
||||
Token::Func(_, dbginf) => dbginf.print(error, arg, source),
|
||||
Token::Var(_, dbginf) => dbginf.print(error, arg, source),
|
||||
|
@ -325,7 +357,7 @@ impl<'a> Token<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
const TOKEN_REGEX_SRC: &'static str = r"(#.*)|(unless|while|loop|break|continue)|(true|false|ye|no|maybe)|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9]+))?\s*=|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9]+))|([A-Za-z_]+)|(\d*\.?\d+)|(!=|==|<=|<=|[&|+\-*/<>])|([(){}])|(\n)";
|
||||
const TOKEN_REGEX_SRC: &'static str = r"(#.*)|(unless|while|loop|break|continue)|(int|rat|bool)|(true|false|ye|no|maybe)|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9]+))?\s*=|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9]+))|([A-Za-z_]+)|(\d*\.?\d+)|(!=|==|<=|<=|[&|+\-*/<>=])|([(){}])|(\n|;)";
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref TOKEN_REGEX: regex::Regex = regex::Regex::new(TOKEN_REGEX_SRC).unwrap();
|
||||
|
@ -363,8 +395,11 @@ pub fn tokenize<'a>(source: &'a str) -> VecDeque<Token<'a>> {
|
|||
|
||||
tokens.push_back(match i {
|
||||
2 => Token::Keyword(Keyword::parse(mat.as_str()), debug_info),
|
||||
3 => Token::Bool(parse_bool(mat.as_str()), debug_info),
|
||||
4 => {
|
||||
3 => {
|
||||
Token::Type(Prim::from(mat.as_str(), &debug_info, source), debug_info)
|
||||
},
|
||||
4 => Token::Bool(parse_bool(mat.as_str()), debug_info),
|
||||
5 => {
|
||||
let var_type = if let Some(mat) = enumerator.next().unwrap().1 {
|
||||
Some(Prim::from(mat.as_str(), &debug_info, source))
|
||||
} else {
|
||||
|
@ -372,15 +407,15 @@ pub fn tokenize<'a>(source: &'a str) -> VecDeque<Token<'a>> {
|
|||
};
|
||||
Token::Assign(mat.as_str(), var_type, debug_info)
|
||||
},
|
||||
6 => {
|
||||
7 => {
|
||||
let var_type = Prim::from(enumerator.next().unwrap().1.unwrap().as_str(), &debug_info, source);
|
||||
Token::Decl(mat.as_str(), var_type, debug_info)
|
||||
},
|
||||
8 => Token::Word(mat.as_str(), debug_info),
|
||||
9 => Token::Number(mat.as_str(), debug_info),
|
||||
10 => Token::Operator(Operator::parse(mat.as_str()), debug_info),
|
||||
11 => Token::Delemiter(mat.as_str().chars().nth(0).unwrap(), debug_info),
|
||||
12 => {
|
||||
9 => Token::Word(mat.as_str(), debug_info),
|
||||
10 => Token::Number(mat.as_str(), NumberClassHint::from(mat.as_str()), debug_info),
|
||||
11 => Token::Operator(Operator::parse(mat.as_str()), debug_info),
|
||||
12 => Token::Delemiter(mat.as_str().chars().nth(0).unwrap(), debug_info),
|
||||
13 => {
|
||||
line_count += 1;
|
||||
Token::LineBreak(debug_info)
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue