Skip to content

Commit 1ab9a93

Browse files
author
DigitalCodeCrafter
committed
added comparisons and booleans
+ added unary negation - no boolean oprations yet
1 parent d64ae55 commit 1ab9a93

22 files changed

Lines changed: 583 additions & 224 deletions

src/ast_interpreter.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
use std::collections::HashMap;
2+
use crate::common::Span;
3+
use crate::syntax::*;
4+
5+
pub struct Env<'a> {
6+
parent: Option<&'a Env<'a>>,
7+
vars: HashMap<&'a str, Value>,
8+
}
9+
10+
#[derive(Debug, Clone, Copy)]
11+
pub enum Value {
12+
Number(f64),
13+
Bool(bool),
14+
Unit,
15+
}
16+
17+
#[derive(Debug)]
18+
pub enum EvalError {
19+
InvalidStatement(Span),
20+
InvalidExpression(Span),
21+
UnknownVariable(String, Span),
22+
InvalidType(Value, Value, Span),
23+
}
24+
25+
pub fn interpret_program<'a>(ast: &'a ParsedAst) -> (HashMap<&'a str, Value>, Vec<EvalError>) {
26+
let mut env = Env { parent: None, vars: HashMap::new() };
27+
let mut errors = Vec::new();
28+
29+
for stmt in &ast.stmts {
30+
match eval_stmt(stmt, &mut env) {
31+
Err(e) => errors.push(e),
32+
Ok(_) => {},
33+
}
34+
}
35+
36+
(env.vars, errors)
37+
}
38+
39+
fn eval_stmt<'a>(stmt: &Stmt<'a>, env: &mut Env<'a>) -> Result<(), EvalError> {
40+
match &stmt.kind {
41+
StmtKind::Let { name, value } => {
42+
let v = eval_expr(value, env)?;
43+
env.vars.insert(*name, v);
44+
Ok(())
45+
}
46+
StmtKind::Expr(expr) => {
47+
eval_expr(expr, env)?;
48+
Ok(())
49+
}
50+
StmtKind::Empty => Ok(()),
51+
StmtKind::Error(_) => Err(EvalError::InvalidStatement(stmt.span)),
52+
}
53+
}
54+
55+
fn eval_expr<'a>(expr: &Expr<'a>, env: &Env<'a>) -> Result<Value, EvalError> {
56+
match &expr.kind {
57+
ExprKind::Literal(Literal::Number { value, .. }) => Ok(Value::Number(*value)),
58+
ExprKind::Literal(Literal::Bool(b)) => Ok(Value::Bool(*b)),
59+
60+
ExprKind::Identifier { name } => {
61+
let mut current = env;
62+
loop {
63+
let found = current.vars.get(name).copied();
64+
65+
if let Some(val) = found {
66+
return Ok(val)
67+
}
68+
69+
match current.parent {
70+
Some(p) => current = p,
71+
None => return Err(EvalError::UnknownVariable(name.to_string(), expr.span)),
72+
}
73+
}
74+
}
75+
76+
ExprKind::UnaryOp { op, expr: inner_expr } => {
77+
let v = eval_expr(inner_expr, env)?;
78+
79+
match (op, v) {
80+
(UnaryOp::Neg, Value::Number(v)) => Ok(Value::Number(-v)),
81+
_ => return Err(EvalError::InvalidType(v, Value::Number(0.0), expr.span))
82+
}
83+
}
84+
85+
ExprKind::BinaryOp { op, left, right } => {
86+
let l = eval_expr(left, env)?;
87+
let r = eval_expr(right, env)?;
88+
89+
match (op, l, r) {
90+
(BinaryOp::Add, Value::Number(l), Value::Number(r)) => Ok(Value::Number(l + r)),
91+
(BinaryOp::Sub, Value::Number(l), Value::Number(r)) => Ok(Value::Number(l - r)),
92+
(BinaryOp::Mul, Value::Number(l), Value::Number(r)) => Ok(Value::Number(l * r)),
93+
(BinaryOp::Div, Value::Number(l), Value::Number(r)) => Ok(Value::Number(l / r)),
94+
95+
(BinaryOp::Gt, Value::Number(l), Value::Number(r)) => Ok(Value::Bool(l > r)),
96+
(BinaryOp::Ge, Value::Number(l), Value::Number(r)) => Ok(Value::Bool(l >= r)),
97+
(BinaryOp::Lt, Value::Number(l), Value::Number(r)) => Ok(Value::Bool(l < r)),
98+
(BinaryOp::Le, Value::Number(l), Value::Number(r)) => Ok(Value::Bool(l <= r)),
99+
100+
(BinaryOp::Eq, Value::Number(l), Value::Number(r)) => Ok(Value::Bool(l == r)),
101+
(BinaryOp::Ne, Value::Number(l), Value::Number(r)) => Ok(Value::Bool(l != r)),
102+
(BinaryOp::Eq, Value::Bool(l), Value::Bool(r)) => Ok(Value::Bool(l != r)),
103+
(BinaryOp::Ne, Value::Bool(l), Value::Bool(r)) => Ok(Value::Bool(l != r)),
104+
_ => return Err(EvalError::InvalidType(l, r, expr.span)),
105+
}
106+
}
107+
108+
ExprKind::Block { stmts, tail_expr } => {
109+
let mut inner_env = Env { parent: Some(env), vars: HashMap::new() };
110+
111+
for stmt in stmts {
112+
eval_stmt(stmt, &mut inner_env)?;
113+
}
114+
115+
tail_expr.as_ref().map(|expr| eval_expr(expr, &inner_env)).unwrap_or(Ok(Value::Unit))
116+
}
117+
118+
ExprKind::Error(_) => Err(EvalError::InvalidExpression(expr.span)),
119+
}
120+
}

src/backend/kerboscript.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ impl KosEmitter {
2424
fn emit_const(&mut self, c: &Const) {
2525
match c {
2626
Const::Number(n) => self.out.push_str(&n.to_string()),
27+
Const::Bool(true) => self.out.push_str("true"),
28+
Const::Bool(false) => self.out.push_str("false"),
2729
Const::Unit => self.out.push_str("0"),
2830
}
2931
}
@@ -43,12 +45,26 @@ impl KosEmitter {
4345
match rval {
4446
RValue::Use(op) => self.emit_operand(op),
4547

48+
RValue::Unary(op, val) => {
49+
let op_str = match op {
50+
UnaryOp::Neg => "-",
51+
};
52+
self.emit(op_str);
53+
self.emit_operand(val);
54+
}
55+
4656
RValue::Binary(op, lhs, rhs) => {
4757
let op_str = match op {
4858
BinaryOp::Add => " + ",
4959
BinaryOp::Sub => " - ",
5060
BinaryOp::Mul => " * ",
5161
BinaryOp::Div => " / ",
62+
BinaryOp::Gt => " > ",
63+
BinaryOp::Ge => " >= ",
64+
BinaryOp::Lt => " < ",
65+
BinaryOp::Le => " <= ",
66+
BinaryOp::Eq => " == ",
67+
BinaryOp::Ne => " <> ",
5268
};
5369
self.emit_operand(lhs);
5470
self.emit(op_str);

src/common/diagnostics.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,22 @@ impl Diagnostic {
5858
}
5959
}
6060

61+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62+
pub struct ErrorGuaranteed(());
63+
6164
pub trait DiagnosticSink {
62-
fn emit(&mut self, diagnostic: Diagnostic);
65+
fn emit(&mut self, diagnostic: Diagnostic) -> ErrorGuaranteed;
6366
}
6467

6568
pub mod sinks {
66-
use super::{Diagnostic, DiagnosticSink, Severity};
69+
use super::{Diagnostic, DiagnosticSink, Severity, ErrorGuaranteed};
6770
pub struct Diagnostics {
6871
pub diagnostics: Vec<Diagnostic>,
6972
}
7073
impl DiagnosticSink for Diagnostics {
71-
fn emit(&mut self, diagnostic: Diagnostic) {
74+
fn emit(&mut self, diagnostic: Diagnostic) -> ErrorGuaranteed {
7275
self.diagnostics.push(diagnostic);
76+
ErrorGuaranteed(())
7377
}
7478
}
7579
impl Diagnostics {
@@ -84,15 +88,18 @@ pub mod sinks {
8488

8589
pub struct IgnoreErrors;
8690
impl DiagnosticSink for IgnoreErrors {
87-
fn emit(&mut self, _: Diagnostic) {}
91+
fn emit(&mut self, _: Diagnostic) -> ErrorGuaranteed {
92+
ErrorGuaranteed(())
93+
}
8894
}
8995

9096
pub struct AssertErrors;
9197
impl DiagnosticSink for AssertErrors {
92-
fn emit(&mut self, diagnostic: Diagnostic) {
98+
fn emit(&mut self, diagnostic: Diagnostic) -> ErrorGuaranteed {
9399
if diagnostic.severity == Severity::Error {
94100
panic!("[AssertErrors] Error: {:?}", diagnostic)
95101
}
102+
ErrorGuaranteed(())
96103
}
97104
}
98-
}
105+
}

src/grammar.ebnf

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,20 @@ Expression = PrattExpr;
1717
(* Expression forms *)
1818
nud = Number
1919
| Identifier
20+
| "true"
21+
| "false"
2022
| "(", Expression, ")"
21-
| "{", { Statement }, "}" (* TODO *)
23+
| "{", { Statement }, "}"
2224
;
2325
24-
led = "+", Expression
26+
led = "==", Expression
27+
| "!=", Expression
28+
| "<", Expression
29+
| "<=", Expression
30+
| ">", Expression
31+
| ">=", Expression
32+
| "+", Expression
2533
| "-", Expression
2634
| "*", Expression
2735
| "/", Expression
28-
;
36+
;

src/interpreter.rs

Lines changed: 0 additions & 95 deletions
This file was deleted.

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ pub mod semantics;
55
pub mod mir;
66
pub mod backend;
77

8-
pub mod interpreter;
8+
pub mod ast_interpreter;
9+
pub mod mir_interpreter;

src/mir/lowerer.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,19 @@ impl MirBuilder<'_> {
7777
self.lower_expr(unused, expr);
7878
}
7979
t::StmtKind::Empty => {},
80-
t::StmtKind::Error => {},
80+
t::StmtKind::Error(_) => {},
8181
}
8282
}
8383

8484
fn lower_expr(&mut self, dest: Place, expr: t::Expr) {
8585
let rval = match expr.kind {
86-
t::ExprKind::Number { value, .. } => RValue::Use(Operand::Const(Const::Number(value))),
86+
t::ExprKind::Literal(t::Literal::Number { value, .. }) => RValue::Use(Operand::Const(Const::Number(value))),
87+
t::ExprKind::Literal(t::Literal::Bool(b)) => RValue::Use(Operand::Const(Const::Bool(b))),
8788

8889
t::ExprKind::Identifier { sym } => match self.env.get(&sym) {
8990
Some(&local) => RValue::Use(Operand::Copy(Place { local, projection: Vec::new() })),
9091
None => RValue::Poison,
91-
},
92+
}
9293

9394
t::ExprKind::BinaryOp { op, left, right } => {
9495
let l_place = Place { local: self.new_local(left.ty.clone()), projection: Vec::new() };
@@ -99,6 +100,12 @@ impl MirBuilder<'_> {
99100
RValue::Binary(op, Operand::Move(l_place), Operand::Move(r_place))
100101
}
101102

103+
t::ExprKind::UnaryOp { op, expr } => {
104+
let e_place = Place { local: self.new_local(expr.ty.clone()), projection: Vec::new() };
105+
self.lower_expr(e_place.clone(), *expr);
106+
RValue::Unary(op, Operand::Move(e_place))
107+
}
108+
102109
t::ExprKind::Block { stmts, tail_expr } => {
103110
self.emit(Instr::Debug(DebugInfo { span: expr.span, kind: DebugKind::EnterScope }));
104111
for stmt in stmts {
@@ -113,7 +120,7 @@ impl MirBuilder<'_> {
113120
}
114121
}
115122

116-
t::ExprKind::Error => RValue::Poison,
123+
t::ExprKind::Error(_) => RValue::Poison,
117124
};
118125

119126
self.emit(Instr::Assign(dest, rval));

0 commit comments

Comments
 (0)