function return type added

This commit is contained in:
Sven Vogel 2022-10-27 07:25:58 +02:00
parent a9b150a40e
commit 6e5461ce33
4 changed files with 130 additions and 73 deletions

View File

@ -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)
}
}
";

View File

@ -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
}
}
}

View File

@ -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
}

View File

@ -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)
// +-------------------------------------------------------------------------------+---------------------------------+
(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, &[
// +-------------------------------------------------------------------------------+---------------------------------+
// | Parameter list of types | result type |
// +-------------------------------------------------------------------------------+---------------------------------+
(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 )
(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)
},