Implement arrays

This commit is contained in:
Daniel M 2022-02-04 18:48:45 +01:00
parent 8b67c4d59c
commit cf2e5348bb
6 changed files with 97 additions and 1 deletions

View File

@ -82,6 +82,13 @@ pub enum Expression {
I64(i64), I64(i64),
/// String literal /// String literal
String(Sid), String(Sid),
/// Array with size
ArrayLiteral(Box<Expression>),
/// Array access with name, stackpos and position
ArrayAccess(Sid, usize, Box<Expression>),
/// Variable /// Variable
Var(Sid, usize), Var(Sid, usize),
/// Binary operation. Consists of type, left hand side and right hand side /// Binary operation. Consists of type, left hand side and right hand side

View File

@ -46,7 +46,6 @@ impl SimpleAstOptimizer {
fn optimize_expr(expr: &mut Expression) { fn optimize_expr(expr: &mut Expression) {
match expr { match expr {
Expression::I64(_) | Expression::String(_) | Expression::Var(_, _) => (),
Expression::BinOp(bo, lhs, rhs) => { Expression::BinOp(bo, lhs, rhs) => {
Self::optimize_expr(lhs); Self::optimize_expr(lhs);
Self::optimize_expr(rhs); Self::optimize_expr(rhs);
@ -99,6 +98,7 @@ impl SimpleAstOptimizer {
_ => (), _ => (),
} }
} }
_ => (),
} }
} }

View File

@ -1,3 +1,5 @@
use std::cell::RefCell;
use crate::{ use crate::{
ast::{BlockScope, BinOpType, Expression, If, Statement, UnOpType, Ast}, ast::{BlockScope, BinOpType, Expression, If, Statement, UnOpType, Ast},
lexer::lex, lexer::lex,
@ -8,6 +10,7 @@ use crate::{
pub enum Value { pub enum Value {
I64(i64), I64(i64),
String(Sid), String(Sid),
Array(RefCell<Vec<Value>>),
} }
#[derive(Default)] #[derive(Default)]
@ -127,13 +130,41 @@ impl Interpreter {
fn resolve_expr(&mut self, expr: &Expression) -> Value { fn resolve_expr(&mut self, expr: &Expression) -> Value {
match expr { match expr {
Expression::I64(val) => Value::I64(*val), Expression::I64(val) => Value::I64(*val),
Expression::ArrayLiteral(size) => {
let size = match self.resolve_expr(size) {
Value::I64(size) => size,
_ => panic!("Array size needs to be I64"),
};
Value::Array(RefCell::new(vec![Value::I64(0); size as usize]))
}
Expression::String(text) => Value::String(text.clone()), Expression::String(text) => Value::String(text.clone()),
Expression::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, lhs, rhs), Expression::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, lhs, rhs),
Expression::UnOp(uo, operand) => self.resolve_unop(uo, operand), Expression::UnOp(uo, operand) => self.resolve_unop(uo, operand),
Expression::Var(name, idx) => self.resolve_var(*name, *idx), Expression::Var(name, idx) => self.resolve_var(*name, *idx),
Expression::ArrayAccess(name, idx, arr_idx) => self.resolve_array_access(*name, *idx, arr_idx),
} }
} }
fn resolve_array_access(&mut self, name: Sid, idx: usize, arr_idx: &Expression) -> Value {
let arr_idx = match self.resolve_expr(arr_idx) {
Value::I64(size) => size,
_ => panic!("Array index needs to be I64"),
};
let val = match self.get_var(idx) {
Some(val) => val,
None => panic!("Variable '{}' used but not declared", self.stringstore.lookup(name).unwrap()),
};
let arr = match val {
Value::Array(arr) => arr,
_ => panic!("Variable '{}' used but not declared", self.stringstore.lookup(name).unwrap()),
};
let arr = arr.borrow_mut();
arr.get(arr_idx as usize).cloned().expect("Runtime error: Invalid array index")
}
fn resolve_var(&mut self, name: Sid, idx: usize) -> Value { fn resolve_var(&mut self, name: Sid, idx: usize) -> Value {
match self.get_var(idx) { match self.get_var(idx) {
Some(val) => val, Some(val) => val,
@ -167,6 +198,24 @@ impl Interpreter {
} }
return rhs; return rhs;
} }
(BinOpType::Assign, Expression::ArrayAccess(name, idx, arr_idx)) => {
let arr_idx = match self.resolve_expr(arr_idx) {
Value::I64(size) => size,
_ => panic!("Array index needs to be I64"),
};
let val = match self.get_var_mut(*idx) {
Some(val) => val,
None => panic!("Runtime Error: Trying to assign value to undeclared variable: {:?}", self.stringstore.lookup(*name)),
};
match val {
Value::Array(arr) => arr.borrow_mut()[arr_idx as usize] = rhs.clone(),
_ => panic!("Variable '{}' used but not declared", self.stringstore.lookup(*name).unwrap()),
}
return rhs;
}
_ => (), _ => (),
} }
@ -202,6 +251,7 @@ impl Interpreter {
fn print_value(&self, val: &Value) { fn print_value(&self, val: &Value) {
match val { match val {
Value::I64(val) => print!("{}", val), Value::I64(val) => print!("{}", val),
Value::Array(val) => print!("{:?}", val.borrow()),
Value::String(text) => print!("{}", self.stringstore.lookup(*text).unwrap()), Value::String(text) => print!("{}", self.stringstore.lookup(*text).unwrap()),
} }
} }

View File

@ -106,6 +106,8 @@ impl<'a> Lexer<'a> {
'{' => tokens.push(Token::LBraces), '{' => tokens.push(Token::LBraces),
'}' => tokens.push(Token::RBraces), '}' => tokens.push(Token::RBraces),
'!' => tokens.push(Token::LNot), '!' => tokens.push(Token::LNot),
'[' => tokens.push(Token::LBracket),
']' => tokens.push(Token::RBracket),
// Special tokens with variable length // Special tokens with variable length

View File

@ -239,6 +239,37 @@ impl<T: Iterator<Item = Token>> Parser<T> {
// Literal String // Literal String
Token::String(text) => Expression::String(self.stringstore.intern_or_lookup(&text)), Token::String(text) => Expression::String(self.stringstore.intern_or_lookup(&text)),
Token::LBracket => {
let size = self.parse_expr();
if !matches!(self.next(), Token::RBracket) {
panic!("Error parsing array literal: Expected closing bracket")
}
Expression::ArrayLiteral(size.into())
}
Token::Ident(name) if matches!(self.peek(), Token::LBracket) => {
let sid = self.stringstore.intern_or_lookup(&name);
let stackpos = self
.varstack
.iter()
.rev()
.position(|it| *it == sid)
.map(|it| self.varstack.len() - it - 1)
.unwrap_or(usize::MAX);
self.next();
let size = self.parse_expr();
if !matches!(self.next(), Token::RBracket) {
panic!("Error parsing array access: Expected closing bracket")
}
Expression::ArrayAccess(sid, stackpos, size.into())
}
Token::Ident(name) => { Token::Ident(name) => {
let sid = self.stringstore.intern_or_lookup(&name); let sid = self.stringstore.intern_or_lookup(&name);
let stackpos = self let stackpos = self

View File

@ -23,6 +23,12 @@ pub enum Token {
/// Else keyword (else) /// Else keyword (else)
Else, Else,
/// Left Bracket ('[')
LBracket,
/// Right Bracket (']')
RBracket,
/// Left Parenthesis ('(') /// Left Parenthesis ('(')
LParen, LParen,