indexing and field access
This commit is contained in:
parent
671301383b
commit
e649cef425
15 changed files with 585 additions and 196 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -223,6 +223,10 @@ dependencies = [
|
|||
"rustyline",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matrix-stdlib"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.1"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = [ "matrix", "matrix-bin" ]
|
||||
members = [ "matrix", "matrix-bin" , "matrix-stdlib"]
|
||||
|
|
5
a.mat
Normal file
5
a.mat
Normal file
|
@ -0,0 +1,5 @@
|
|||
a = 0;
|
||||
|
||||
while a < 1000000000 { a = a + 1 };
|
||||
|
||||
|
|
@ -54,6 +54,7 @@ impl<'a> State<'a> {
|
|||
let compiler = CompilerBuilder::new()
|
||||
.repl(repl)
|
||||
.debug(args.debug)
|
||||
.names(vm.names())
|
||||
.build();
|
||||
|
||||
(Self { parser, vm, compiler, repl }, file)
|
||||
|
|
8
matrix-stdlib/Cargo.toml
Normal file
8
matrix-stdlib/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "matrix-stdlib"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
14
matrix-stdlib/src/lib.rs
Normal file
14
matrix-stdlib/src/lib.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
pub fn add(left: usize, right: usize) -> usize {
|
||||
left + right
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
|
@ -31,7 +31,6 @@ pub enum BinaryOp {
|
|||
LessEquals,
|
||||
GreaterThan,
|
||||
LessThan,
|
||||
Range,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
@ -46,7 +45,7 @@ pub enum Expr {
|
|||
|
||||
Index(Box<Expr>, Vec<Expr>),
|
||||
FnCall(Box<Expr>, Vec<Expr>),
|
||||
FieldAccess(Box<Expr>, Box<Expr>),
|
||||
FieldAccess(Box<Expr>, Rc<str>),
|
||||
|
||||
List(InlineList),
|
||||
Matrix(InlineMatrix),
|
||||
|
@ -60,7 +59,6 @@ pub enum Expr {
|
|||
If(Box<Expr>, Box<Expr>, Option<Box<Expr>>),
|
||||
Function(Rc<str>, Vec<Rc<str>>, Box<Expr>),
|
||||
|
||||
|
||||
Loop(Box<Expr>),
|
||||
While(Box<Expr>, Box<Expr>),
|
||||
DoWhile(Box<Expr>, Box<Expr>),
|
||||
|
@ -178,10 +176,9 @@ pub fn optimize(expr: Expr) -> Result<Expr> {
|
|||
.map(optimize)
|
||||
.collect::<Result<Vec<Expr>>>()?)
|
||||
}
|
||||
E::FieldAccess(key, val) => {
|
||||
let key = optimize(*key)?;
|
||||
let val = optimize(*val)?;
|
||||
E::FieldAccess(Box::new(key), Box::new(val))
|
||||
E::FieldAccess(expr, ident) => {
|
||||
let expr = optimize(*expr)?;
|
||||
E::FieldAccess(Box::new(expr), ident)
|
||||
},
|
||||
E::List(list) =>
|
||||
E::List(list.into_iter()
|
||||
|
@ -333,7 +330,6 @@ impl From<Token> for BinaryOp {
|
|||
Divide => Self::Divide,
|
||||
Modulo => Self::Modulo,
|
||||
Power => Self::Power,
|
||||
Range => Self::Range,
|
||||
_ => panic!("aaaaa")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@ pub enum Instruction {
|
|||
NewTable(u16),
|
||||
NewMatrix(u16, u8),
|
||||
|
||||
Field(u16),
|
||||
StoreField(u16),
|
||||
Index(u8),
|
||||
StoreIndex(u8),
|
||||
|
||||
|
@ -112,6 +114,8 @@ impl Display for Instruction {
|
|||
JumpFalse(idx) => write!(f, "jumpf \x1b[33m{idx}\x1b[0m"),
|
||||
Call(arity) => write!(f, "call \x1b[35m{arity}\x1b[0m"),
|
||||
Return => write!(f, "return"),
|
||||
Field(name_idx) => write!(f, "field \x1b[33m{name_idx}\x1b[0m"),
|
||||
StoreField(name_idx) => write!(f, "store field \x1b[33m{name_idx}\x1b[0m"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,11 @@ use Expr as E;
|
|||
|
||||
pub struct CompilerBuilder<'c> {
|
||||
globals: Rc<RefCell<Vec<Rc<str>>>>,
|
||||
names: Rc<RefCell<Vec<Rc<str>>>>,
|
||||
repl: bool,
|
||||
debug: bool,
|
||||
name: Rc<str>,
|
||||
parent: Option<&'c Compiler<'c>>
|
||||
parent: Option<&'c Compiler<'c>>,
|
||||
}
|
||||
|
||||
impl<'c> CompilerBuilder<'c> {
|
||||
|
@ -22,6 +23,7 @@ impl<'c> CompilerBuilder<'c> {
|
|||
debug: false,
|
||||
name: "<root>".into(),
|
||||
parent: None,
|
||||
names: Rc::new(RefCell::new(Vec::new()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +42,11 @@ impl<'c> CompilerBuilder<'c> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn names(mut self, names: Rc<RefCell<Vec<Rc<str>>>>) -> Self {
|
||||
self.names = names;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn parent(mut self, parent: &'c Compiler) -> Self {
|
||||
self.parent = Some(parent);
|
||||
self
|
||||
|
@ -53,6 +60,7 @@ impl<'c> CompilerBuilder<'c> {
|
|||
pub fn build(self) -> Compiler<'c> {
|
||||
Compiler {
|
||||
name: self.name,
|
||||
names: self.names,
|
||||
parent: self.parent,
|
||||
globals: self.globals,
|
||||
repl: self.repl,
|
||||
|
@ -73,6 +81,7 @@ pub struct Compiler<'c> {
|
|||
|
||||
locals: Vec<Rc<Local>>,
|
||||
globals: Rc<RefCell<Vec<Rc<str>>>>,
|
||||
names: Rc<RefCell<Vec<Rc<str>>>>,
|
||||
|
||||
root_is_block: bool,
|
||||
|
||||
|
@ -207,6 +216,12 @@ impl<'c> Compiler<'c> {
|
|||
None
|
||||
}
|
||||
|
||||
fn get_name(&mut self, name: Rc<str>) -> usize {
|
||||
let idx = self.names.borrow().len();
|
||||
self.names.borrow_mut().push(name);
|
||||
idx
|
||||
}
|
||||
|
||||
fn emit_const(&mut self, val: Value) {
|
||||
// TODO: find constant if already exists
|
||||
self.chunk.constants.push(val);
|
||||
|
@ -244,7 +259,7 @@ impl<'c> Compiler<'c> {
|
|||
|
||||
fn compile_expr(&mut self, expr: &Expr) -> Result<()> {
|
||||
match expr {
|
||||
E::NoOp => {},
|
||||
E::NoOp => self.emit(I::Nil),
|
||||
E::If(cond, ifb, elseb) => {
|
||||
self.compile_expr(cond)?;
|
||||
let jmpidx = self.emit_temp();
|
||||
|
@ -375,6 +390,18 @@ impl<'c> Compiler<'c> {
|
|||
self.emit(I::CreateLocal);
|
||||
}
|
||||
},
|
||||
E::Index(expr, params) => {
|
||||
self.compile_expr(expr)?;
|
||||
for param in params {
|
||||
self.compile_expr(param)?;
|
||||
}
|
||||
self.emit(I::StoreIndex(params.len() as u8));
|
||||
},
|
||||
E::FieldAccess(expr, ident) => {
|
||||
self.compile_expr(expr)?;
|
||||
let name = self.get_name(ident.clone());
|
||||
self.emit(I::StoreField(name as u16));
|
||||
}
|
||||
_ => return Err(self::Error::InvAssign(*lhs.clone()).into())
|
||||
}
|
||||
}
|
||||
|
@ -387,7 +414,13 @@ impl<'c> Compiler<'c> {
|
|||
self.compile_expr(rhs)?;
|
||||
self.emit(I::BinaryOp(*op));
|
||||
},
|
||||
E::Index(_, _) => return Err(self::Error::NotImplemented("indexing").into()),
|
||||
E::Index(expr, params) => {
|
||||
self.compile_expr(expr)?;
|
||||
for param in params {
|
||||
self.compile_expr(param)?;
|
||||
}
|
||||
self.emit(I::Index(params.len() as u8))
|
||||
},
|
||||
E::FnCall(fun, params) => {
|
||||
for expr in params {
|
||||
self.compile_expr(expr)?;
|
||||
|
@ -395,7 +428,11 @@ impl<'c> Compiler<'c> {
|
|||
self.compile_expr(fun)?;
|
||||
self.emit(I::Call(params.len() as u8));
|
||||
},
|
||||
E::FieldAccess(_, _) => return Err(self::Error::NotImplemented("filed access").into()),
|
||||
E::FieldAccess(expr, field) => {
|
||||
self.compile_expr(expr)?;
|
||||
let idx = self.get_name(field.clone());
|
||||
self.emit(I::Field(idx as u16))
|
||||
}
|
||||
E::List(list) => {
|
||||
for expr in list {
|
||||
self.compile_expr(expr)?;
|
||||
|
|
146
matrix/src/gc.rs
146
matrix/src/gc.rs
|
@ -1,112 +1,126 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
use std::{ops::{Index, IndexMut, Deref, DerefMut}, marker::PhantomData, ptr::NonNull, fmt::{Debug, Display}};
|
||||
|
||||
pub struct Gc<T> {
|
||||
ptr: NonNull<GcInner<T>>,
|
||||
phantom: PhantomData<GcInner<T>>,
|
||||
phantom: PhantomData<GcInner<T>>
|
||||
}
|
||||
|
||||
pub struct GcInner<T> {
|
||||
struct GcInner<T> {
|
||||
rc: usize,
|
||||
data: T,
|
||||
data: T
|
||||
}
|
||||
|
||||
impl<T> Gc<T> {
|
||||
pub fn new(data: T) -> Gc<T> {
|
||||
pub fn new(data: T) -> Self {
|
||||
let boxed = Box::new(GcInner {
|
||||
rc: 1,
|
||||
data,
|
||||
});
|
||||
Self {
|
||||
ptr: NonNull::new(Box::into_raw(boxed)).unwrap(),
|
||||
phantom: PhantomData,
|
||||
phantom: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> From<Rc<T>> for Gc<T> {
|
||||
fn from(value: Rc<T>) -> Self {
|
||||
Self::new(Rc::unwrap_or_clone(value))
|
||||
impl <T: Clone> Gc<T> {
|
||||
pub fn clone_inside(&mut self) -> Self {
|
||||
unsafe {
|
||||
let data = self.ptr.as_mut().data.clone();
|
||||
Self::new(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Gc<T> {
|
||||
fn from(value: T) -> Self {
|
||||
Self::new(value)
|
||||
Gc::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IndexMut<Idx>, Idx> IndexMut<Idx> for Gc<T> {
|
||||
fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
|
||||
self.deref_mut().index_mut(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Index<Idx>, Idx> Index<Idx> for Gc<T> {
|
||||
type Output = T::Output;
|
||||
|
||||
fn index(&self, index: Idx) -> &Self::Output {
|
||||
self.deref().index(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for Gc<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe {
|
||||
&mut self.ptr.as_mut().data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Gc<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
let inner = unsafe { self.ptr.as_ref() };
|
||||
&inner.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Debug> Debug for Gc<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let inner = unsafe { self.ptr.as_ref() };
|
||||
write!(f, "{:?}", inner.data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Display> Display for Gc<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let inner = unsafe { self.ptr.as_ref() };
|
||||
write!(f, "{}", inner.data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq> PartialEq for Gc<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let inner = unsafe { self.ptr.as_ref() };
|
||||
let other = unsafe { other.ptr.as_ref() };
|
||||
inner.data == other.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd> PartialOrd for Gc<T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
let inner = unsafe { self.ptr.as_ref() };
|
||||
let other = unsafe { other.ptr.as_ref() };
|
||||
inner.data.partial_cmp(&other.data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> DerefMut for Gc<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
let inner = unsafe { self.ptr.as_mut() };
|
||||
if inner.rc > 1 {
|
||||
*self = Self::new(inner.data.clone());
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe {
|
||||
&self.ptr.as_ref().data
|
||||
}
|
||||
&mut inner.data
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: PartialEq> PartialEq for Gc<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.deref().eq(other.deref())
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: Iterator> Iterator for Gc<T> {
|
||||
type Item = T::Item;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.deref_mut().next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq> Eq for Gc<T> {}
|
||||
|
||||
impl<T> Clone for Gc<T> {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = unsafe { self.ptr.as_ptr().as_mut().unwrap() };
|
||||
inner.rc += 1;
|
||||
Self {
|
||||
ptr: self.ptr,
|
||||
phantom: PhantomData,
|
||||
unsafe {
|
||||
let inner = self.ptr.as_ptr().as_mut().unwrap();
|
||||
inner.rc += 1;
|
||||
|
||||
Self {
|
||||
ptr: self.ptr,
|
||||
phantom: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for Gc<T> {
|
||||
fn drop(&mut self) {
|
||||
let inner = unsafe { self.ptr.as_mut() };
|
||||
inner.rc -= 1;
|
||||
if inner.rc > 0 {
|
||||
return;
|
||||
unsafe {
|
||||
let inner = self.ptr.as_mut();
|
||||
if inner.rc > 1 {
|
||||
inner.rc -= 1;
|
||||
} else {
|
||||
let _ = Box::from_raw(self.ptr.as_ptr());
|
||||
}
|
||||
}
|
||||
unsafe { let _ = Box::from_raw(self.ptr.as_ptr()); }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Debug> Debug for Gc<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self.deref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Display> Display for Gc<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.deref())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,9 +38,7 @@ pub enum Token {
|
|||
LeftBrack,
|
||||
RightBrack,
|
||||
LeftBrace,
|
||||
LeftLeftBrace,
|
||||
RightBrace,
|
||||
RightRightBrace,
|
||||
Assign,
|
||||
Access,
|
||||
SemiColon,
|
||||
|
@ -48,6 +46,15 @@ pub enum Token {
|
|||
ThinArrow,
|
||||
Comma,
|
||||
Range,
|
||||
Colon,
|
||||
|
||||
// math
|
||||
Regex(RegexToken),
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Complex(f64),
|
||||
String(Rc<str>),
|
||||
Ident(Rc<str>),
|
||||
|
||||
// equality
|
||||
Equal,
|
||||
|
@ -67,14 +74,6 @@ pub enum Token {
|
|||
BitwiseOr,
|
||||
BitwiseXor,
|
||||
|
||||
// math
|
||||
Regex(RegexToken),
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Complex(f64),
|
||||
String(Rc<str>),
|
||||
Ident(Rc<str>),
|
||||
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
|
@ -82,6 +81,22 @@ pub enum Token {
|
|||
Modulo,
|
||||
Power,
|
||||
|
||||
AssignAnd,
|
||||
AssignOr,
|
||||
|
||||
AssignBitwiseShiftLeft,
|
||||
AssignBitwiseShiftRight,
|
||||
AssignBitwiseAnd,
|
||||
AssignBitwiseOr,
|
||||
AssignBitwiseXor,
|
||||
|
||||
AssignAdd,
|
||||
AssignSubtract,
|
||||
AssignMultiply,
|
||||
AssignDivide,
|
||||
AssignModulo,
|
||||
AssignPower,
|
||||
|
||||
// keywords
|
||||
If,
|
||||
Else,
|
||||
|
@ -193,7 +208,7 @@ impl Lexer {
|
|||
}
|
||||
|
||||
fn skip_whitespace(&mut self, ignore_newlines: bool) {
|
||||
while self.peek().is_whitespace() && (!ignore_newlines || self.peek() != '\n') {
|
||||
while self.peek().is_whitespace() && (ignore_newlines || self.peek() != '\n') {
|
||||
self.next();
|
||||
}
|
||||
}
|
||||
|
@ -420,42 +435,62 @@ impl Lexer {
|
|||
}
|
||||
|
||||
Ok(match char {
|
||||
'\n' => SemiColon,
|
||||
'(' => LeftParen,
|
||||
')' => RightParen,
|
||||
'[' => LeftBrack,
|
||||
']' => RightBrack,
|
||||
'{' => {
|
||||
match next {
|
||||
'{' => {
|
||||
self.next();
|
||||
LeftLeftBrace
|
||||
}
|
||||
_ => LeftBrace
|
||||
}
|
||||
},
|
||||
'}' => {
|
||||
match next {
|
||||
'}' => {
|
||||
self.next();
|
||||
RightRightBrace
|
||||
}
|
||||
_ => RightBrace
|
||||
}
|
||||
},
|
||||
'{' => LeftBrace,
|
||||
'}' => RightBrace,
|
||||
':' => Colon,
|
||||
';' => SemiColon,
|
||||
'+' => Add,
|
||||
'+' => {
|
||||
match next {
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignAdd
|
||||
}
|
||||
_ => Add
|
||||
}
|
||||
},
|
||||
'/' => {
|
||||
match next {
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignDivide
|
||||
}
|
||||
_ => Divide
|
||||
}
|
||||
},
|
||||
'%' => {
|
||||
match next {
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignModulo
|
||||
}
|
||||
_ => Modulo
|
||||
}
|
||||
},
|
||||
',' => Comma,
|
||||
'*' => {
|
||||
match next {
|
||||
'*' => {
|
||||
self.next();
|
||||
Power
|
||||
match self.peek() {
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignPower
|
||||
},
|
||||
_ => Power
|
||||
}
|
||||
},
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignMultiply
|
||||
}
|
||||
_ => Multiply
|
||||
}
|
||||
},
|
||||
'/' => Divide,
|
||||
'%' => Modulo,
|
||||
'!' => {
|
||||
match next {
|
||||
'=' => {
|
||||
|
@ -469,8 +504,18 @@ impl Lexer {
|
|||
match next {
|
||||
'&' => {
|
||||
self.next();
|
||||
And
|
||||
}
|
||||
match self.peek() {
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignAnd
|
||||
},
|
||||
_ => And
|
||||
}
|
||||
},
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignBitwiseAnd
|
||||
},
|
||||
_ => BitwiseAnd
|
||||
}
|
||||
},
|
||||
|
@ -478,8 +523,18 @@ impl Lexer {
|
|||
match next {
|
||||
'|' => {
|
||||
self.next();
|
||||
Or
|
||||
}
|
||||
match self.peek() {
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignOr
|
||||
},
|
||||
_ => Or
|
||||
}
|
||||
},
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignBitwiseOr
|
||||
},
|
||||
_ => BitwiseOr
|
||||
}
|
||||
},
|
||||
|
@ -488,7 +543,11 @@ impl Lexer {
|
|||
'>' => {
|
||||
self.next();
|
||||
ThinArrow
|
||||
}
|
||||
},
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignSubtract
|
||||
},
|
||||
_ => Subtract
|
||||
}
|
||||
},
|
||||
|
@ -509,7 +568,13 @@ impl Lexer {
|
|||
match next {
|
||||
'>' => {
|
||||
self.next();
|
||||
BitwiseShiftRight
|
||||
match self.peek() {
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignBitwiseShiftRight
|
||||
},
|
||||
_ => BitwiseShiftRight
|
||||
}
|
||||
}
|
||||
'=' => {
|
||||
self.next();
|
||||
|
@ -522,7 +587,13 @@ impl Lexer {
|
|||
match next {
|
||||
'<' => {
|
||||
self.next();
|
||||
BitwiseShiftLeft
|
||||
match self.peek() {
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignBitwiseShiftLeft
|
||||
},
|
||||
_ => BitwiseShiftLeft
|
||||
}
|
||||
}
|
||||
'=' => {
|
||||
self.next();
|
||||
|
@ -531,7 +602,15 @@ impl Lexer {
|
|||
_ => LessThan
|
||||
}
|
||||
},
|
||||
'^' => BitwiseXor,
|
||||
'^' => {
|
||||
match next {
|
||||
'=' => {
|
||||
self.next();
|
||||
AssignBitwiseXor
|
||||
},
|
||||
_ => BitwiseXor
|
||||
}
|
||||
}
|
||||
'\'' | '\"' => String(self.lex_string(char)?),
|
||||
'r' => {
|
||||
match next {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{fmt::Display, rc::Rc};
|
||||
use num_complex::Complex64;
|
||||
|
||||
use crate::{lex::{Lexer, self, Token}, ast::{Expr, BinaryOp, UnaryOp, optimize}, gc::Gc, value::{Value, self}, Result};
|
||||
use crate::{lex::{Lexer, self, Token}, ast::{Expr, BinaryOp, UnaryOp, optimize}, value::{Value, self}, Result};
|
||||
|
||||
use Value as V;
|
||||
use Expr as E;
|
||||
|
@ -230,9 +230,10 @@ impl Parser {
|
|||
}
|
||||
|
||||
fn parse_table(&mut self) -> Result<Expr> {
|
||||
self.force_token(T::LeftLeftBrace)?;
|
||||
self.force_token(T::Colon)?;
|
||||
self.force_token(T::LeftBrace)?;
|
||||
let mut table = Vec::new();
|
||||
if self.lexer.peek_token()? == T::RightRightBrace {
|
||||
if self.lexer.peek_token()? == T::RightBrace {
|
||||
self.lexer.next_token()?;
|
||||
return Ok(E::Table(table))
|
||||
}
|
||||
|
@ -244,7 +245,7 @@ impl Parser {
|
|||
let next = self.lexer.next_token()?;
|
||||
match next {
|
||||
T::Comma => continue,
|
||||
T::RightRightBrace => break,
|
||||
T::RightBrace => break,
|
||||
_ => return Err(Error::UnexpectedToken(next).into())
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +403,7 @@ impl Parser {
|
|||
T::Int(i) => E::Literal(V::Int(i)),
|
||||
T::Float(f) => E::Literal(V::Float(f)),
|
||||
T::Complex(c) => E::Literal(V::Complex(Complex64::new(0.0, c))),
|
||||
T::Regex(r) => E::Literal(V::Regex(Gc::new(r.into()))),
|
||||
T::Regex(r) => E::Literal(V::Regex(Rc::new(r.into()))),
|
||||
T::String(s) => E::Literal(V::String(s.to_string().into())),
|
||||
T::True => E::Literal(V::Bool(true)),
|
||||
T::False => E::Literal(V::Bool(false)),
|
||||
|
@ -431,7 +432,7 @@ impl Parser {
|
|||
Ok(E::Continue)
|
||||
},
|
||||
LeftBrack => self.parse_matrix(),
|
||||
LeftLeftBrace => self.parse_table(),
|
||||
Colon => self.parse_table(),
|
||||
LeftParen => self.parse_paren(),
|
||||
_ => self.parse_value(),
|
||||
}
|
||||
|
@ -444,8 +445,8 @@ impl Parser {
|
|||
match tok {
|
||||
T::Access => {
|
||||
self.force_token(T::Access)?;
|
||||
let temp = self.parse_term()?;
|
||||
expr = E::FieldAccess(Box::new(expr), Box::new(temp));
|
||||
let temp = self.parse_ident()?;
|
||||
expr = E::FieldAccess(Box::new(expr), temp);
|
||||
},
|
||||
_ => break
|
||||
}
|
||||
|
@ -563,13 +564,66 @@ impl Parser {
|
|||
}
|
||||
|
||||
fn parse_expr(&mut self) -> Result<Expr> {
|
||||
use BinaryOp as B;
|
||||
let expr = self.parse_expr_or()?;
|
||||
let tok = self.lexer.peek_token_nl()?;
|
||||
Ok(match tok {
|
||||
T::Assign => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr),Box::new(self.parse_expr()?))
|
||||
}
|
||||
E::Assign(Box::new(expr.clone()),Box::new(self.parse_expr()?))
|
||||
},
|
||||
T::AssignAnd => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::And(Box::new(expr), Box::new(self.parse_expr()?))))
|
||||
},
|
||||
T::AssignOr => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::Or(Box::new(expr), Box::new(self.parse_expr()?))))
|
||||
},
|
||||
T::AssignAdd => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Add)))
|
||||
},
|
||||
T::AssignSubtract => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Subtract)))
|
||||
},
|
||||
T::AssignMultiply => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Multiply)))
|
||||
},
|
||||
T::AssignDivide => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Divide)))
|
||||
},
|
||||
T::AssignModulo => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Modulo)))
|
||||
},
|
||||
T::AssignPower => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::Power)))
|
||||
},
|
||||
T::AssignBitwiseAnd => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::BitwiseAnd)))
|
||||
},
|
||||
T::AssignBitwiseOr => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::BitwiseOr)))
|
||||
},
|
||||
T::AssignBitwiseXor => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::BitwiseXor)))
|
||||
},
|
||||
T::AssignBitwiseShiftLeft => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::BitwiseShiftLeft)))
|
||||
},
|
||||
T::AssignBitwiseShiftRight => {
|
||||
self.lexer.next_token_nl()?;
|
||||
E::Assign(Box::new(expr.clone()),Box::new(E::BinaryOp(Box::new(expr), Box::new(self.parse_expr()?), B::BitwiseShiftRight)))
|
||||
},
|
||||
_ => expr
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use num_complex::Complex64;
|
|||
use num_rational::Rational64;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::{ast::{Expr, BinaryOp, UnaryOp}, gc::Gc, chunk::Function, Result};
|
||||
use crate::{ast::{Expr, BinaryOp, UnaryOp}, chunk::Function, Result, gc::Gc};
|
||||
|
||||
pub type List = Vec<Value>;
|
||||
pub type Matrix = (usize, usize, Vec<Value>);
|
||||
|
@ -43,12 +43,14 @@ pub enum Error {
|
|||
Exponent(Value, Value),
|
||||
Compare(Value, Value),
|
||||
IndexOutOfBounds(usize, usize),
|
||||
Index(Value, Value),
|
||||
CannotIndex(Value),
|
||||
BadIndex(Value, Value),
|
||||
Concat(Value, Value),
|
||||
Bitwise(Value, Value),
|
||||
DivideByZero,
|
||||
ZeroExpZero,
|
||||
CannotHash(Value),
|
||||
FieldAccess(Value),
|
||||
}
|
||||
|
||||
impl Display for self::Error {
|
||||
|
@ -64,12 +66,14 @@ impl Display for self::Error {
|
|||
Exponent(a, b) => write!(f, "cannot compute {a:?} pow {b:?}"),
|
||||
Compare(a, b) => write!(f, "cannot compare {a:?} and {b:?}"),
|
||||
IndexOutOfBounds(a, b) => write!(f, "index {a} out of bounds for list of length {b}"),
|
||||
Index(a, b) => write!(f, "cannot index {a:?} with {b:?}"),
|
||||
BadIndex(a, b) => write!(f, "cannot index {a:?} with {b:?}"),
|
||||
CannotIndex(a) => write!(f, "cannot index {a:?}"),
|
||||
Concat(a, b) => write!(f, "cannot concat {a:?} and {b:?}"),
|
||||
Bitwise(a, b) => write!(f, "cannot bitwise between {a:?} and {b:?}"),
|
||||
DivideByZero => write!(f, "attempted to divide by zero"),
|
||||
ZeroExpZero => write!(f, "cannot exponent zero with zero"),
|
||||
CannotHash(v) => write!(f, "cannot hash {v:?}"),
|
||||
FieldAccess(a) => write!(f, "{a:?} cannot be field accessed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,8 +88,8 @@ pub enum Value {
|
|||
Float(f64),
|
||||
Ratio(Rational64),
|
||||
Complex(Complex64),
|
||||
Regex(Gc<Regex>),
|
||||
String(Gc<String>),
|
||||
Regex(Rc<Regex>),
|
||||
String(Rc<String>),
|
||||
List(Gc<List>),
|
||||
Matrix(Gc<Matrix>),
|
||||
Table(Gc<Table>),
|
||||
|
@ -153,21 +157,21 @@ impl Value {
|
|||
Float(l) => format!("{l}"),
|
||||
Ratio(r) => format!("{r}"),
|
||||
Complex(c) => format!("{c}"),
|
||||
Regex(r) => format!("{r}"),
|
||||
Regex(r) => format!("/{r}/"),
|
||||
String(s) => format!("{s}"),
|
||||
List(l) => {
|
||||
let mut str = "[ ".to_string();
|
||||
let mut str = "[".to_string();
|
||||
for (i, el) in l.iter().enumerate() {
|
||||
if i != 0 {
|
||||
str.push_str(" ");
|
||||
}
|
||||
str.push_str(&el.boring_print());
|
||||
}
|
||||
str.push_str(" ]");
|
||||
str.push_str("]");
|
||||
str
|
||||
},
|
||||
Matrix(m) => {
|
||||
let mut str = "[[ ".to_string();
|
||||
let mut str = "[[".to_string();
|
||||
for (i, el) in m.2.iter().enumerate() {
|
||||
if i != 0 {
|
||||
if (i % m.1) == 0 {
|
||||
|
@ -178,11 +182,11 @@ impl Value {
|
|||
}
|
||||
str.push_str(&el.boring_print());
|
||||
}
|
||||
str.push_str(" ]]");
|
||||
str.push_str("]]");
|
||||
str
|
||||
},
|
||||
Table(t) => {
|
||||
let mut str = "{{ ".to_string();
|
||||
let mut str = "{".to_string();
|
||||
for (i, (key, val)) in t.0.iter().enumerate() {
|
||||
if i != 0 {
|
||||
str.push_str(", ");
|
||||
|
@ -191,7 +195,7 @@ impl Value {
|
|||
str.push_str(" = ");
|
||||
str.push_str(&val.boring_print());
|
||||
}
|
||||
str.push_str(" }}");
|
||||
str.push_str("}");
|
||||
str
|
||||
},
|
||||
Function(fun) => {
|
||||
|
@ -212,18 +216,18 @@ impl Value {
|
|||
Regex(_) => format!("\x1b[31m{}\x1b[0m", self.boring_print()),
|
||||
String(_) => format!("\x1b[32m'{}'\x1b[0m", self.boring_print()),
|
||||
List(l) => {
|
||||
let mut str = "[ ".to_string();
|
||||
let mut str = "[".to_string();
|
||||
for (i, el) in l.iter().enumerate() {
|
||||
if i != 0 {
|
||||
str.push_str(" ");
|
||||
}
|
||||
str.push_str(&el.pretty_print());
|
||||
}
|
||||
str.push_str(" ]");
|
||||
str.push_str("]");
|
||||
str
|
||||
},
|
||||
Matrix(m) => {
|
||||
let mut str = "[[ ".to_string();
|
||||
let mut str = "[[".to_string();
|
||||
for (i, el) in m.2.iter().enumerate() {
|
||||
if i != 0 {
|
||||
if (i % m.1) == 0 {
|
||||
|
@ -234,11 +238,11 @@ impl Value {
|
|||
}
|
||||
str.push_str(&el.pretty_print());
|
||||
}
|
||||
str.push_str(" ]]");
|
||||
str.push_str("]]");
|
||||
str
|
||||
},
|
||||
Table(t) => {
|
||||
let mut str = "{{ ".to_string();
|
||||
let mut str = "{".to_string();
|
||||
for (i, (key, val)) in t.0.iter().enumerate() {
|
||||
if i != 0 {
|
||||
str.push_str(", ");
|
||||
|
@ -247,7 +251,7 @@ impl Value {
|
|||
str.push_str(" = ");
|
||||
str.push_str(&val.pretty_print());
|
||||
}
|
||||
str.push_str(" }}");
|
||||
str.push_str("}");
|
||||
str
|
||||
},
|
||||
Function(_) => {
|
||||
|
@ -295,10 +299,10 @@ impl Add for Value {
|
|||
(Float(x), Float(y)) => Ok(Float(x + y)),
|
||||
(Ratio(x), Ratio(y)) => Ok(Ratio(x + y)),
|
||||
(Complex(x), Complex(y)) => Ok(Complex(x + y)),
|
||||
(String(str), value) => Ok(String(Gc::new(
|
||||
(String(str), value) => Ok(String(Rc::new(
|
||||
format!("{str}{}", value.boring_print())
|
||||
))),
|
||||
(value, String(str)) => Ok(String(Gc::new(
|
||||
(value, String(str)) => Ok(String(Rc::new(
|
||||
format!("{}{str}", value.boring_print())
|
||||
))),
|
||||
(List(mut l1), List(l2)) => {
|
||||
|
@ -420,28 +424,18 @@ fn ipow(n: i64, d: i64, p: i64) -> Result<(i64, i64)> {
|
|||
}
|
||||
|
||||
impl Value {
|
||||
|
||||
pub fn modulo(self, rhs: Value) -> Result<Self> {
|
||||
use Value::*;
|
||||
match promote(self, rhs) {
|
||||
(Int(x), Int(y)) => Ok(Int(x.rem_euclid(y))),
|
||||
(Float(x), Float(y)) => Ok(Float(x.rem_euclid(y))),
|
||||
(Ratio(_x), Ratio(_y)) => todo!("ratio modulo"),
|
||||
(Complex(_x), Complex(_y)) => todo!("complex modulo"),
|
||||
(Int(x), Int(y)) => Ok(Int(x % y)),
|
||||
(Float(x), Float(y)) => Ok(Float(x % y)),
|
||||
(Ratio(x), Ratio(y)) => Ok(Ratio(x % y)),
|
||||
(Complex(x), Complex(y)) => Ok(Complex(x % y)),
|
||||
(l, r) => Err(Error::Modulo(r, l).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn int_div(self, rhs: Value) -> Result<Self> {
|
||||
use Value::*;
|
||||
match promote(self, rhs) {
|
||||
(Int(x), Int(y)) => Ok(Int(x.div_euclid(y))),
|
||||
(Float(x), Float(y)) => Ok(Float(x.div_euclid(y))),
|
||||
(Ratio(_x), Ratio(_y)) => todo!("ratio integer division"),
|
||||
(Complex(_x), Complex(_y)) => todo!("complex integer division"),
|
||||
(l, r) => Err(Error::Divide(l, r).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pow(self, rhs: Value) -> Result<Self> {
|
||||
use Value::*;
|
||||
if let (Ratio(x), Int(y)) = (&self, &rhs) {
|
||||
|
@ -518,24 +512,123 @@ impl Value {
|
|||
.map_or_else(|| Err(Error::Compare(self.clone(), other.clone()).into()), Ok)
|
||||
}
|
||||
|
||||
pub fn store_index(&self, _other: &Vec<Self>, _value: &Self) -> Result<()> {
|
||||
todo!()
|
||||
fn index_single(&self, index: &Value) -> Result<Self> {
|
||||
use Value as V;
|
||||
match (self, index) {
|
||||
(V::Table(t), index) => {
|
||||
Ok(t.get(index)?.unwrap_or(&Value::Nil).clone())
|
||||
},
|
||||
(V::List(l), V::Int(i)) => {
|
||||
if *i < 0 || *i as usize >= l.len() {
|
||||
return Err(Error::IndexOutOfBounds(*i as usize, l.len()).into())
|
||||
}
|
||||
Ok(l[*i as usize].clone())
|
||||
}
|
||||
_ => return Err(self::Error::BadIndex(self.clone(), index.clone()).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn index(&self, _other: &Vec<Self>) -> Result<Self> {
|
||||
todo!()
|
||||
//use Value::*;
|
||||
//match (self, other) {
|
||||
// (List(l), Int(i)) => {
|
||||
// if *i >= 0 && *i < l.len() as i64 {
|
||||
// Ok(l[*i as usize].clone())
|
||||
// } else {
|
||||
// Err(Error::IndexOutOfBounds(*i as usize, l.len()))
|
||||
// }
|
||||
// },
|
||||
// (l, r) => Err(Error::Index(l.clone(), r.clone()))
|
||||
//}
|
||||
}
|
||||
fn index_multiple(&self, indexes: &Vec<Value>) -> Result<Self> {
|
||||
use Value as V;
|
||||
match self {
|
||||
V::List(..) => {
|
||||
let mut ret = Vec::new();
|
||||
for index in indexes {
|
||||
let res = self.index_single(index)?;
|
||||
ret.push(res);
|
||||
}
|
||||
Ok(V::List(ret.into()))
|
||||
}
|
||||
V::Table(..) => {
|
||||
let mut ret = ValueMap::new();
|
||||
for index in indexes {
|
||||
let res = self.index_single(index)?;
|
||||
ret.insert(index.clone(), res)?;
|
||||
}
|
||||
Ok(V::Table(ret.into()))
|
||||
}
|
||||
_ => return Err(self::Error::CannotIndex(self.clone()).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn index(&self, index: &Vec<Value>) -> Result<Self> {
|
||||
if index.len() == 0 {
|
||||
Ok(self.clone())
|
||||
} else if index.len() == 1 {
|
||||
self.index_single(&index[0])
|
||||
} else {
|
||||
self.index_multiple(index)
|
||||
}
|
||||
}
|
||||
|
||||
fn store_index_single(&mut self, index: &Value, store: Value) -> Result<()> {
|
||||
use Value as V;
|
||||
let err = self.clone();
|
||||
match (self, index) {
|
||||
(V::Table(t), index) => {
|
||||
t.insert(index.clone(), store)
|
||||
},
|
||||
(V::List(l), V::Int(i)) => {
|
||||
if *i < 0 || *i as usize >= l.len() {
|
||||
return Err(Error::IndexOutOfBounds(*i as usize, l.len()).into())
|
||||
}
|
||||
l[*i as usize] = store;
|
||||
Ok(())
|
||||
}
|
||||
_ => return Err(self::Error::BadIndex(err, index.clone()).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn store_index_multiple(&mut self, indexes: &Vec<Value>, store: Value) -> Result<()> {
|
||||
use Value as V;
|
||||
match self {
|
||||
V::List(..) => {
|
||||
for index in indexes {
|
||||
self.store_index_single(index, store.clone())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
V::Table(..) => {
|
||||
for index in indexes {
|
||||
self.store_index_single(index, store.clone())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => return Err(self::Error::CannotIndex(self.clone()).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store_index(&mut self, index: &Vec<Value>, store: Value) -> Result<()> {
|
||||
if index.len() == 0 {
|
||||
Ok(())
|
||||
} else if index.len() == 1 {
|
||||
self.store_index_single(&index[0], store)
|
||||
} else {
|
||||
self.store_index_multiple(index, store)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store_field_access(&mut self, ident: &str, val: Value) -> Result<()> {
|
||||
use Value as V;
|
||||
match self {
|
||||
V::Table(t) => {
|
||||
let key = V::String(Rc::new(ident.to_string()));
|
||||
Ok(t.insert(key, val)?)
|
||||
},
|
||||
_ => return Err(self::Error::FieldAccess(self.clone()).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn field_access(&self, ident: &str) -> Result<Self> {
|
||||
use Value as V;
|
||||
match self {
|
||||
V::Table(t) => {
|
||||
let key = V::String(Rc::new(ident.to_string()));
|
||||
Ok(t.get(&key)?.unwrap_or(&V::Nil).clone())
|
||||
},
|
||||
_ => return Err(self::Error::FieldAccess(self.clone()).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn binary_op(op: BinaryOp, lhs: Value, rhs: Value) -> Result<Self> {
|
||||
use BinaryOp::*;
|
||||
|
@ -557,7 +650,6 @@ impl Value {
|
|||
LessEquals => Ok(Self::Bool(lhs <= rhs)),
|
||||
GreaterThan => Ok(Self::Bool(lhs > rhs)),
|
||||
LessThan => Ok(Self::Bool(lhs < rhs)),
|
||||
Range => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{rc::Rc, fmt::{Debug, Display}, usize, ops::{Index, IndexMut}, collections::HashMap};
|
||||
use std::{rc::Rc, fmt::{Debug, Display}, usize, ops::{Index, IndexMut}, collections::HashMap, cell::RefCell};
|
||||
use crate::{value::{Value, self, ValueMap}, gc::Gc, chunk::{Function, Instruction}, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -108,6 +108,7 @@ pub struct Vm {
|
|||
locals: Stack<Value>,
|
||||
frames: Vec<StackFrame>,
|
||||
globals: HashMap<u16, Value>,
|
||||
names: Rc<RefCell<Vec<Rc<str>>>>,
|
||||
}
|
||||
|
||||
impl Vm {
|
||||
|
@ -120,12 +121,17 @@ impl Vm {
|
|||
self.stack.pop()
|
||||
}
|
||||
|
||||
pub fn names(&self) -> Rc<RefCell<Vec<Rc<str>>>> {
|
||||
self.names.clone()
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
stack: Stack::new(),
|
||||
locals: Stack::new(),
|
||||
frames: Vec::new(),
|
||||
globals: HashMap::new(),
|
||||
names: Rc::new(RefCell::new(Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,11 +141,12 @@ impl Vm {
|
|||
use Instruction::*;
|
||||
let ins = frame.fun.body.code[frame.ip].clone();
|
||||
frame.ip += 1;
|
||||
|
||||
match ins {
|
||||
NoOp => {},
|
||||
CreateLocal => self.locals.push(self.stack.pop()),
|
||||
LoadLocal(idx) => {self.stack.push(self.locals[idx as usize].clone());},
|
||||
StoreLocal(idx) => self.stack[frame.bp + idx as usize] = self.pop(),
|
||||
StoreLocal(idx) => self.locals[frame.bp + idx as usize] = self.pop(),
|
||||
DiscardLocals(count) => {self.locals.truncate(self.locals.len() - count as usize)},
|
||||
LoadGlobal(idx) => {
|
||||
let val = self.globals
|
||||
|
@ -187,18 +194,6 @@ impl Vm {
|
|||
let domain = list.len() / codomain;
|
||||
self.push(Value::Matrix(Gc::new((domain, codomain, list.inner))));
|
||||
}
|
||||
Index(count) => {
|
||||
let index = self.stack.split_off(self.stack.len() - count as usize);
|
||||
let collection = self.pop();
|
||||
let value = collection.index(&index.inner)?;
|
||||
self.stack.push(value);
|
||||
},
|
||||
StoreIndex(count) => {
|
||||
let value = self.pop();
|
||||
let index = self.stack.split_off(self.stack.len() - count as usize);
|
||||
let collection = self.pop();
|
||||
collection.store_index(&index.inner, &value)?;
|
||||
}
|
||||
Jump(idx) => frame.ip = idx as usize,
|
||||
JumpTrue(idx) => {
|
||||
if !!self.pop() {
|
||||
|
@ -231,6 +226,29 @@ impl Vm {
|
|||
self.push(ret);
|
||||
frame = prev_frame;
|
||||
},
|
||||
Field(name_idx) => {
|
||||
let expr = self.pop();
|
||||
let name = self.names.borrow()[name_idx as usize].clone();
|
||||
self.push(expr.field_access(&name)?);
|
||||
},
|
||||
StoreField(name_idx) => {
|
||||
let mut expr = self.pop();
|
||||
let value = self.pop();
|
||||
let name = self.names.borrow()[name_idx as usize].clone();
|
||||
expr.store_field_access(&name, value)?;
|
||||
},
|
||||
Index(count) => {
|
||||
let index = self.stack.split_off(self.stack.len() - count as usize);
|
||||
let collection = self.pop();
|
||||
let value = collection.index(&index.inner)?;
|
||||
self.stack.push(value);
|
||||
},
|
||||
StoreIndex(count) => {
|
||||
let index = self.stack.split_off(self.stack.len() - count as usize);
|
||||
let mut collection = self.pop();
|
||||
let value = self.pop();
|
||||
collection.store_index(&index.inner, value)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(self.pop())
|
||||
|
|
63
syntax_thing
Normal file
63
syntax_thing
Normal file
|
@ -0,0 +1,63 @@
|
|||
root => root_expr*
|
||||
root_expr => function
|
||||
root_expr => expr
|
||||
function => FUNCTION IDENT params block
|
||||
params => IDENT
|
||||
params => OP CP
|
||||
params => OP params_impl
|
||||
params_impl => IDENT COMMA params_impl
|
||||
params_impl => IDENT CP
|
||||
block => expr*
|
||||
expr => if_expr
|
||||
if_expr => IF math_expr block ELSE if_expr
|
||||
if_expr => IF math_expr block ELSE block
|
||||
if_expr => IF math_expr block
|
||||
expr => DO block WHILE math_expr
|
||||
expr => WHILE math_expr block
|
||||
expr => LET IDENT EQ math_expr END
|
||||
expr => LET IDENT END
|
||||
expr => IDENT EQ math_expr END
|
||||
expr => block
|
||||
expr => RETURN math_expr END
|
||||
expr => BREAK
|
||||
expr => CONTINUE
|
||||
expr => math_expr END
|
||||
math_expr => (math_expr_and OR)* math_expr_and
|
||||
math_expr_and => math_expr_and AND math_expr_and
|
||||
math_expr_and => math_expr_compare
|
||||
math_expr_compare => math_expr_compare <COMPARE> math_expr_compare
|
||||
|
||||
power_term => power_term POWER power_term
|
||||
power_term => power_term BIT_AND power_term
|
||||
power_term => power_term BIT_OR power_term
|
||||
power_term => power_term SHIFT_LEFT power_term
|
||||
power_term => power_term SHIFT_RIGHT power_term
|
||||
power_term => term
|
||||
term => value
|
||||
term => tuple
|
||||
term => list
|
||||
term => table
|
||||
term => IDENT
|
||||
value => INT DIVIDE INT
|
||||
value => INT
|
||||
value => FLOAT
|
||||
value => COMPLEX
|
||||
value => STRING
|
||||
value => REGEX
|
||||
value => TRUE
|
||||
value => FALSE
|
||||
tuple => OP CP
|
||||
tuple => OP tuple_impl
|
||||
tuple_impl => math_expr COMMA tuple_impl
|
||||
tuple_impl => math_expr CP
|
||||
list => LBRK RBRK
|
||||
list => LBRK list_impl
|
||||
list_impl => math_expr COMMA tuple_impl
|
||||
list_impl => math_expr RBRK
|
||||
table => LBRC RBRC
|
||||
table => LBRC table_impl
|
||||
table_impl => table_key EQ math_expr COMMA table_impl
|
||||
table_impl => table_key EQ math_expr RBRC
|
||||
table_key => LBRK math_expr RBRK
|
||||
table_key => IDENT
|
||||
table_key => STRING
|
Loading…
Reference in a new issue