Slightly change call semantics, add looping construct, inline some JS
This commit is contained in:
		@@ -1,9 +1,10 @@
 | 
				
			|||||||
## Obligatory
 | 
					## Obligatory
 | 
				
			||||||
fizzbuzz <- x ->
 | 
					fizzbuzz <- ->
 | 
				
			||||||
  if x % 15 = 0 print("fizzbuzz")
 | 
					  loop(range(100), x ->
 | 
				
			||||||
  elif x % 3 = 0 print("fizz")
 | 
					    if x % 15 = 0 print("fizzbuzz")
 | 
				
			||||||
  elif x % 5 = 0 print("buzz")
 | 
					    elif x % 3 = 0 print("fizz")
 | 
				
			||||||
  else print(x)
 | 
					    elif x % 5 = 0 print("buzz")
 | 
				
			||||||
  if x < 100 fizzbuzz(x + 1) ## TODO add looping construct(s)
 | 
					    else print(x)
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fizzbuzz(1)
 | 
					fizzbuzz()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -120,18 +120,28 @@ pub fn emit_expr(w: &mut dyn Write, expr: &parser::Expr, ctx: &mut LexicalContex
 | 
				
			|||||||
	    write!(w, "{}", atom)?;
 | 
						    write!(w, "{}", atom)?;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	parser::Expr::Funcall(id, args) => {
 | 
						parser::Expr::Funcall(id, args) => {
 | 
				
			||||||
	    if let Some((last, butlast)) = args.split_last() {
 | 
						    write!(w, "{}", munge(id))?;
 | 
				
			||||||
		write!(w, "T({}, ", munge(id))?;
 | 
						    if args.is_empty() {
 | 
				
			||||||
		for expr in butlast {
 | 
							write!(w, "()")?;
 | 
				
			||||||
		    emit_expr(w, expr, ctx)?;
 | 
						    } else if ctx.contains(id) {
 | 
				
			||||||
		    write!(w, ", ")?;
 | 
							// Use deelang calling semantics
 | 
				
			||||||
 | 
							for arg in args {
 | 
				
			||||||
 | 
							    write!(w, "(")?;
 | 
				
			||||||
 | 
							    emit_expr(w, arg, ctx)?;
 | 
				
			||||||
 | 
							    write!(w, ")")?
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						    } else {
 | 
				
			||||||
 | 
							// Use JS calling semantics
 | 
				
			||||||
 | 
							write!(w, "(")?;
 | 
				
			||||||
 | 
							let (last, butlast) = args.split_last().unwrap();
 | 
				
			||||||
 | 
							for arg in butlast {
 | 
				
			||||||
 | 
							    emit_expr(w, arg, ctx)?;
 | 
				
			||||||
 | 
							    write!(w, ",")?
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		emit_expr(w, last, ctx)?;
 | 
							emit_expr(w, last, ctx)?;
 | 
				
			||||||
		write!(w, ")")?;
 | 
							write!(w, ")")?;
 | 
				
			||||||
	    } else {
 | 
					 | 
				
			||||||
		write!(w, "{}", munge(id))?;
 | 
					 | 
				
			||||||
		write!(w, "()")?;
 | 
					 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
 | 
								
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	parser::Expr::Funcdef(arg, body) => {
 | 
						parser::Expr::Funcdef(arg, body) => {
 | 
				
			||||||
	    if let Some(arg) = arg {
 | 
						    if let Some(arg) = arg {
 | 
				
			||||||
@@ -174,9 +184,9 @@ pub fn emit_expr(w: &mut dyn Write, expr: &parser::Expr, ctx: &mut LexicalContex
 | 
				
			|||||||
	    write!(w, " == ")?;
 | 
						    write!(w, " == ")?;
 | 
				
			||||||
	    emit_expr(w, e2.as_ref(), ctx)?;
 | 
						    emit_expr(w, e2.as_ref(), ctx)?;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	parser::Expr::Lt(e1, e2) => {
 | 
						parser::Expr::Relop(op, e1, e2) => {
 | 
				
			||||||
	    emit_expr(w, e1.as_ref(), ctx)?;
 | 
						    emit_expr(w, e1.as_ref(), ctx)?;
 | 
				
			||||||
	    write!(w, " < ")?;
 | 
						    write!(w, " {} ", op)?;
 | 
				
			||||||
	    emit_expr(w, e2.as_ref(), ctx)?;
 | 
						    emit_expr(w, e2.as_ref(), ctx)?;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	_ => todo!(),
 | 
						_ => todo!(),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,16 @@
 | 
				
			|||||||
const print = console.log
 | 
					const print = console.log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function T(f, ...args) {
 | 
					function loop(seq, f) {
 | 
				
			||||||
  let res = f;
 | 
					  for (el of seq) {
 | 
				
			||||||
  for (arg of args) {
 | 
					    f(el)
 | 
				
			||||||
    res = res(arg);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return res;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function range(x) {
 | 
				
			||||||
 | 
					  const ret = []
 | 
				
			||||||
 | 
					  for (let i = 0; i < x; i++) {
 | 
				
			||||||
 | 
					    ret.push(i);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return ret
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ pub enum Expr {
 | 
				
			|||||||
    Div(Box<Expr>, Box<Expr>),
 | 
					    Div(Box<Expr>, Box<Expr>),
 | 
				
			||||||
    Mod(Box<Expr>, Box<Expr>),
 | 
					    Mod(Box<Expr>, Box<Expr>),
 | 
				
			||||||
    Equal(Box<Expr>, Box<Expr>),
 | 
					    Equal(Box<Expr>, Box<Expr>),
 | 
				
			||||||
    Lt(Box<Expr>, Box<Expr>),
 | 
					    Relop(String, Box<Expr>, Box<Expr>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type Block = Vec<Stmt>;
 | 
					pub type Block = Vec<Stmt>;
 | 
				
			||||||
@@ -60,7 +60,8 @@ peg::parser! {
 | 
				
			|||||||
            e:expr() stop() { Stmt::BareExpr(e) }
 | 
					            e:expr() stop() { Stmt::BareExpr(e) }
 | 
				
			||||||
        rule expr() -> Expr = precedence! {
 | 
					        rule expr() -> Expr = precedence! {
 | 
				
			||||||
	    e1:(@) "=" _ e2:@ { Expr::Equal(Box::new(e1), Box::new(e2)) }
 | 
						    e1:(@) "=" _ e2:@ { Expr::Equal(Box::new(e1), Box::new(e2)) }
 | 
				
			||||||
	    e1:(@) "<" _ e2:@ { Expr::Lt(Box::new(e1), Box::new(e2)) }
 | 
						    --
 | 
				
			||||||
 | 
						    e1:(@) r:relop() e2:@ { Expr::Relop(r, Box::new(e1), Box::new(e2)) }
 | 
				
			||||||
	    --
 | 
						    --
 | 
				
			||||||
            "-" _ e1:@ { Expr::UnaryMinus(Box::new(e1)) }
 | 
					            "-" _ e1:@ { Expr::UnaryMinus(Box::new(e1)) }
 | 
				
			||||||
            --
 | 
					            --
 | 
				
			||||||
@@ -87,10 +88,12 @@ peg::parser! {
 | 
				
			|||||||
            = i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i.to_string() }
 | 
					            = i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i.to_string() }
 | 
				
			||||||
        rule assignment() -> Stmt
 | 
					        rule assignment() -> Stmt
 | 
				
			||||||
            = i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) }
 | 
					            = i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) }
 | 
				
			||||||
 | 
						rule relop() -> String
 | 
				
			||||||
 | 
						    = r:$("<" / ">" / "<=" / ">=") _ { r.to_string() } 
 | 
				
			||||||
        rule num() -> f64
 | 
					        rule num() -> f64
 | 
				
			||||||
            = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() }
 | 
					            = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() }
 | 
				
			||||||
        rule funcall() -> Expr
 | 
					        rule funcall() -> Expr
 | 
				
			||||||
            = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) }
 | 
					            = i:id() "(" _ e:(expr() ** ("," _)) __* ")" _ { Expr::Funcall(i, e) }
 | 
				
			||||||
        rule funcdef() -> Expr
 | 
					        rule funcdef() -> Expr
 | 
				
			||||||
            = i:id()? "->" _ b:(block()) { Expr::Funcdef(i, b) }
 | 
					            = i:id()? "->" _ b:(block()) { Expr::Funcdef(i, b) }
 | 
				
			||||||
        rule conditional() -> Stmt
 | 
					        rule conditional() -> Stmt
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user