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)
|
1. a COMEFROM keyword (inverse goto)
|
||||||
2. a `don't` code block which never executes
|
2. a `don't` code block which never executes
|
||||||
3. `rand(x)` returns x, always.
|
3. no if. only `unless`, an inverted version of if. Meaning a block gets executed if the expression is false
|
||||||
4. 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. three spaces start a single line comment
|
5. many ways of making comments: `// comment`, `:REM: comment`, `# comment`, `-- comment --` cuz we can
|
||||||
6. many ways of making comments: `// comment`, `:REM: comment`, `# comment`, `-- comment --` cuz we can
|
|
||||||
|
|
||||||
### Keywords
|
### Keywords
|
||||||
|
|
||||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -24,18 +24,14 @@ pi = rat 3.1415926535
|
||||||
foo(x :int, y: rat) = bool {
|
foo(x :int, y: rat) = bool {
|
||||||
yield maybe
|
yield maybe
|
||||||
}
|
}
|
||||||
comment
|
|
||||||
main {
|
main {
|
||||||
-- comment --
|
|
||||||
unless 3 > 4 {
|
unless 3 > 4 {
|
||||||
a = 4 - 5; // also comment
|
a = 4 - 5;
|
||||||
b:rat = 0.3 + 7
|
b:rat = 0.3 + 7
|
||||||
|
|
||||||
t = foo(a, b) :REM: comment 3
|
t = foo(a, b)
|
||||||
}
|
|
||||||
|
|
||||||
don't {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|
|
@ -84,6 +84,11 @@ pub struct Scope<'a> {
|
||||||
pub args: Option<&'a Vec<(&'a str, Prim)>>,
|
pub args: Option<&'a Vec<(&'a str, Prim)>>,
|
||||||
/// stack of scoped block variables
|
/// stack of scoped block variables
|
||||||
pub vars: Vec<Vec<(String, Option<Prim>)>>,
|
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> {
|
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 {
|
match keyword {
|
||||||
Keyword::If | Keyword::While => {
|
Keyword::If | Keyword::While => {
|
||||||
if operands.len() != 1 {
|
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) {
|
fn parse_exprs<'a>(funcs: &mut Vec<Func<'a>>, declrs: &Vec<Declr<'a>>, source: &'a str) {
|
||||||
let mut scope = Scope {
|
let mut scope = Scope {
|
||||||
args: None,
|
args: None,
|
||||||
vars: vec![]
|
vars: vec![],
|
||||||
|
func_return_typ: None,
|
||||||
|
cond_scope: false,
|
||||||
|
yields: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (x, func) in funcs.iter_mut().enumerate() {
|
for (x, func) in funcs.iter_mut().enumerate() {
|
||||||
match func.expr.as_mut().expect("Function has no body") {
|
match func.expr.as_mut().expect("Function has no body") {
|
||||||
Expr::Block(block) => {
|
Expr::Block(block) => {
|
||||||
scope.args = declrs[x].args.as_ref();
|
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")
|
_ => panic!("Fatal-Compilier-Error: function must have a block")
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ impl Operator {
|
||||||
"^" => Operator::Xor,
|
"^" => Operator::Xor,
|
||||||
|
|
||||||
"==" => Operator::Eq,
|
"==" => Operator::Eq,
|
||||||
"<" => Operator::Lt,
|
"<" => Operator::Lt,
|
||||||
">" => Operator::Gt,
|
">" => Operator::Gt,
|
||||||
"<=" => Operator::LtEq,
|
"<=" => Operator::LtEq,
|
||||||
">=" => Operator::GtEq,
|
">=" => Operator::GtEq,
|
||||||
"!=" => Operator::NotEq,
|
"!=" => Operator::NotEq,
|
||||||
|
@ -108,9 +108,9 @@ impl Operator {
|
||||||
match self {
|
match self {
|
||||||
Operator::Add | Operator::Sub | Operator::Mul | Operator::Div=> {
|
Operator::Add | Operator::Sub | Operator::Mul | Operator::Div=> {
|
||||||
let types_valid = Self::check_types(operands, &[
|
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::Int, Prim::Int ], Prim::Int),
|
||||||
(vec![Prim::Rat, Prim::Rat ], Prim::Rat),
|
(vec![Prim::Rat, Prim::Rat ], Prim::Rat),
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::Int ], Prim::Int),
|
(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 => {
|
Operator::Eq | Operator::NotEq | Operator::Lt | Operator::Gt | Operator::GtEq | Operator::LtEq => {
|
||||||
let types_valid = Self::check_types(operands, &[
|
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::Int, Prim::Int ], Prim::Bool ),
|
||||||
(vec![Prim::Rat, Prim::Rat ], Prim::Bool ),
|
(vec![Prim::Rat, Prim::Rat ], Prim::Bool ),
|
||||||
(vec![Prim::UntypedNum(NumberClassHint::Int), Prim::Int ], 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! {
|
lazy_static::lazy_static! {
|
||||||
static ref TOKEN_REGEX: regex::Regex = regex::Regex::new(TOKEN_REGEX_SRC).unwrap();
|
static ref TOKEN_REGEX: regex::Regex = regex::Regex::new(TOKEN_REGEX_SRC).unwrap();
|
||||||
|
|
Loading…
Reference in New Issue