Implement arrays
This commit is contained in:
parent
8b67c4d59c
commit
cf2e5348bb
@ -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
|
||||||
|
|||||||
@ -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 {
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user