added yield

This commit is contained in:
Sven Vogel 2022-10-27 21:34:31 +02:00
parent b42f49c340
commit 37671f4550
5 changed files with 67 additions and 26 deletions

View File

@ -6,10 +6,9 @@ It contains features such as:
1. a COMEFROM keyword (inverse goto)
2. a `don't` code block which never executes
3. `rand(x)` returns x, always.
4. no if. only `unless`, an inverted version of if. Meaning a block gets executed if the expression is false
5. three spaces start a single line comment
6. many ways of making comments: `// comment`, `:REM: comment`, `# comment`, `-- comment --` cuz we can
3. no if. only `unless`, an inverted version of if. Meaning a block gets executed if the expression is false
4. three spaces start a single line comment
5. many ways of making comments: `// comment`, `:REM: comment`, `# comment`, `-- comment --` cuz we can
### Keywords

View File

@ -24,18 +24,14 @@ pi = rat 3.1415926535
foo(x :int, y: rat) = bool {
yield maybe
}
comment
main {
-- comment --
main {
unless 3 > 4 {
a = 4 - 5; // also comment
a = 4 - 5;
b:rat = 0.3 + 7
t = foo(a, b) :REM: comment 3
}
don't {
t = foo(a, b)
}
}
";

View File

@ -84,6 +84,11 @@ pub struct Scope<'a> {
pub args: Option<&'a Vec<(&'a str, Prim)>>,
/// stack of scoped block variables
pub vars: Vec<Vec<(String, Option<Prim>)>>,
pub func_return_typ: Option<Prim>,
/// if we safely yielded sth
pub yields: bool,
/// if the current location in the scope is fixed in execution (no loop, no unless)
pub cond_scope: bool
}
impl<'a> Scope<'a> {

View File

@ -316,7 +316,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) {
fn process_keyword(keyword: Keyword, _: &Vec<Declr>, scope: &mut Scope, operands: &mut Vec<Prim>, dbginf: &crate::token::DebugInfo, source: &str) {
match keyword {
Keyword::If | Keyword::While => {
if operands.len() != 1 {
@ -334,6 +334,36 @@ fn process_keyword(keyword: Keyword, _: &Vec<Declr>, _: &mut Scope, operands: &m
}
}
},
Keyword::Return => {
if scope.func_return_typ.is_some() {
dbginf.print(MessageType::Error, "cannot return function, did u mean to use `yield`?", source);
panic!();
}
}
Keyword::Yield => {
if operands.len() != 1 {
dbginf.print(MessageType::Error, format!("Expected single value but got {} values", operands.len()).as_str(), source);
panic!();
}
if let Some(operand) = operands.pop() {
if let Some(typ) = scope.func_return_typ {
if typ != operand {
dbginf.print(MessageType::Error, format!("Expected {:?} but got {:?}", typ, operand).as_str(), source);
panic!();
}
if scope.cond_scope {
scope.yields = true;
}
} else {
dbginf.print(MessageType::Error, format!("Function does not return anything").as_str(), source);
panic!();
}
} else {
dbginf.print(MessageType::Error, format!("Yield must return something").as_str(), source);
panic!();
}
}
_ => ()
}
}
@ -518,15 +548,26 @@ fn parse_block<'a>(block: &mut Block<'a>, declrs: &Vec<Declr<'a>>, scope: &mut S
fn parse_exprs<'a>(funcs: &mut Vec<Func<'a>>, declrs: &Vec<Declr<'a>>, source: &'a str) {
let mut scope = Scope {
args: None,
vars: vec![]
vars: vec![],
func_return_typ: None,
cond_scope: false,
yields: false,
};
for (x, func) in funcs.iter_mut().enumerate() {
match func.expr.as_mut().expect("Function has no body") {
Expr::Block(block) => {
scope.args = declrs[x].args.as_ref();
scope.func_return_typ = declrs[x].result_typ;
scope.cond_scope = false;
scope.yields = false;
parse_block(block, declrs, &mut scope, source)
parse_block(block, declrs, &mut scope, source);
if scope.func_return_typ.is_some() && !scope.yields {
crate::message(MessageType::Error, format!("Function {} missing return value at some point", declrs[x]));
panic!();
}
},
_ => panic!("Fatal-Compilier-Error: function must have a block")
}
@ -545,6 +586,6 @@ pub fn parse<'a>(tokens: &mut VecDeque<crate::Token<'a>>, source: &'a str) -> Ve
for (x, f) in funcs.iter().enumerate() {
println!("{:#?}{:#?}", declrs[x], f);
}
funcs
}

View File

@ -36,8 +36,8 @@ impl Operator {
"^" => Operator::Xor,
"==" => Operator::Eq,
"<" => Operator::Lt,
">" => Operator::Gt,
"<" => Operator::Lt,
">" => Operator::Gt,
"<=" => Operator::LtEq,
">=" => Operator::GtEq,
"!=" => Operator::NotEq,
@ -108,9 +108,9 @@ 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 |
// +-------------------------------------------------------------------------------+---------------------------------+
// +------------------------------------------------------------------------------------+---------------------------------+
// | 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),
@ -150,9 +150,9 @@ 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 |
// +-------------------------------------------------------------------------------+---------------------------------+
// +------------------------------------------------------------------------------------+---------------------------------+
// | 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 ),
@ -373,7 +373,7 @@ impl<'a> Token<'a> {
}
}
const TOKEN_REGEX_SRC: &'static str = r"(#.*|--.*--|//.*|:REM:.*| .*)|(unless|while|loop|break|cont|ret|yield)|(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)|(;)";
const TOKEN_REGEX_SRC: &'static str = r"(#.*)|(unless|while|loop|break|cont|ret|yield)|(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();