added yield
This commit is contained in:
parent
b42f49c340
commit
37671f4550
|
@ -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
|
||||
|
||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -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)
|
||||
}
|
||||
}
|
||||
";
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue