Add functions and a print function
This commit is contained in:
parent
86c2b13d1a
commit
8b60677123
@ -1 +1,3 @@
|
|||||||
print();
|
let otus = "Hello, world!";
|
||||||
|
let dotus = otus;
|
||||||
|
print(dotus);
|
@ -2,9 +2,10 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use super::errors::CompilerError;
|
use super::errors::CompilerError;
|
||||||
use super::parser::{Expression, LiteralPattern, ParsedReid, Pattern, Position, Statement};
|
use super::parser::{Expression, LiteralPattern, ParsedReid, Pattern, Position, Statement};
|
||||||
use super::vm::VariableType;
|
use super::vm::{BuiltinFunctionDef, FunctionDef, FunctionSignature, VariableType};
|
||||||
|
|
||||||
type Variable = (HeapID, VariableType);
|
type Variable = (HeapID, VariableType);
|
||||||
|
pub type FuncID = usize;
|
||||||
pub type HeapID = usize;
|
pub type HeapID = usize;
|
||||||
pub type RegID = usize;
|
pub type RegID = usize;
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ pub enum Command {
|
|||||||
AssignVariable(HeapID, RegID), // Assign variable from registery at RegID
|
AssignVariable(HeapID, RegID), // Assign variable from registery at RegID
|
||||||
VarToReg(HeapID, RegID), // Bring Variable to registery at RegID
|
VarToReg(HeapID, RegID), // Bring Variable to registery at RegID
|
||||||
StringLit(String), // Bring String Literal to Stack
|
StringLit(String), // Bring String Literal to Stack
|
||||||
|
FunctionCall(FuncID), // Call Function at FuncID
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Compiler {
|
pub struct Compiler {
|
||||||
@ -40,11 +42,22 @@ impl Compiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_builtin_functions<T: Into<Vec<FunctionSignature>>>(mut self, list: T) -> Compiler {
|
||||||
|
self.add_builtin_functions(list.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn compile(mut self) -> Result<CompiledReid, CompilerError> {
|
pub fn compile(mut self) -> Result<CompiledReid, CompilerError> {
|
||||||
self.handle_expression(self.parsed.0.clone())?;
|
self.handle_expression(self.parsed.0.clone())?;
|
||||||
Ok(CompiledReid { list: self.list })
|
Ok(CompiledReid { list: self.list })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_builtin_functions<T: Into<Vec<FunctionSignature>>>(&mut self, list: T) {
|
||||||
|
for func in list.into() {
|
||||||
|
self.root_scope.add_builtin_function(func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_expression(
|
fn handle_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
exp: Expression,
|
exp: Expression,
|
||||||
@ -62,7 +75,26 @@ impl Compiler {
|
|||||||
self.list.push(Command::EndScope);
|
self.list.push(Command::EndScope);
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
Expression::FunctionCall(..) => Err(CompilerError::Fatal),
|
Expression::FunctionCall(pos, name, args) => {
|
||||||
|
let mut arguments = Vec::new();
|
||||||
|
|
||||||
|
for expr in args {
|
||||||
|
if let Some(vtype) = self.handle_expression(expr)? {
|
||||||
|
arguments.push(vtype);
|
||||||
|
} else {
|
||||||
|
return Err(CompilerError::CanNotAssignVoidType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(func) = self
|
||||||
|
.root_scope
|
||||||
|
.find_function(&FunctionSignature::new(name.clone(), arguments.clone()))
|
||||||
|
{
|
||||||
|
self.list.push(Command::FunctionCall(func.0));
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Err(CompilerError::FunctionNotFound(pos, name, arguments))
|
||||||
|
}
|
||||||
|
}
|
||||||
Expression::ValueRef(_, val) => match val {
|
Expression::ValueRef(_, val) => match val {
|
||||||
Pattern::IdentPattern(pos, ident) => {
|
Pattern::IdentPattern(pos, ident) => {
|
||||||
if let Some(var) = self.root_scope.get(ident.clone()) {
|
if let Some(var) = self.root_scope.get(ident.clone()) {
|
||||||
@ -123,6 +155,7 @@ impl Compiler {
|
|||||||
pub struct Scope {
|
pub struct Scope {
|
||||||
counter: HeapID,
|
counter: HeapID,
|
||||||
variables: HashMap<String, Variable>,
|
variables: HashMap<String, Variable>,
|
||||||
|
functions: Vec<FunctionSignature>,
|
||||||
inner_scope: Option<Box<Scope>>,
|
inner_scope: Option<Box<Scope>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +174,25 @@ impl Scope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_function(&self, signature: &FunctionSignature) -> Option<(usize, &FunctionSignature)> {
|
||||||
|
let mut found = None;
|
||||||
|
for (idx, func) in self.functions.iter().enumerate() {
|
||||||
|
if func == signature {
|
||||||
|
found = Some((idx, func));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_builtin_function(&mut self, function: FunctionSignature) -> bool {
|
||||||
|
if self.find_function(&function).is_some() {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
self.functions.push(function);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn add_var(
|
fn add_var(
|
||||||
&mut self,
|
&mut self,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
|
@ -3,6 +3,8 @@ use std::fmt;
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
|
use super::vm::VariableType;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum GenericError {
|
pub enum GenericError {
|
||||||
StdIOError(io::Error),
|
StdIOError(io::Error),
|
||||||
@ -64,6 +66,7 @@ pub enum CompilerError {
|
|||||||
InvalidScopeExit(Position),
|
InvalidScopeExit(Position),
|
||||||
LetFailed(Position, Box<CompilerError>),
|
LetFailed(Position, Box<CompilerError>),
|
||||||
CanNotAssignVoidType,
|
CanNotAssignVoidType,
|
||||||
|
FunctionNotFound(Position, String, Vec<VariableType>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompilerError {
|
impl CompilerError {
|
||||||
@ -92,12 +95,35 @@ impl Display for CompilerError {
|
|||||||
CompilerError::LetFailed(pos, error) => {
|
CompilerError::LetFailed(pos, error) => {
|
||||||
format!("Let statement failed at {}:\n {}", pos, error)
|
format!("Let statement failed at {}:\n {}", pos, error)
|
||||||
}
|
}
|
||||||
CompilerError::CanNotAssignVoidType => format!("Can not assign void type to variable"),
|
CompilerError::CanNotAssignVoidType => format!("Can not assign void type here"),
|
||||||
|
CompilerError::FunctionNotFound(pos, name, params) => format!(
|
||||||
|
"Function with signature {}{} not found at {}",
|
||||||
|
name,
|
||||||
|
ParamList(params.clone()),
|
||||||
|
pos
|
||||||
|
),
|
||||||
};
|
};
|
||||||
write!(f, "{}", text)
|
write!(f, "{}", text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ParamList(Vec<VariableType>);
|
||||||
|
|
||||||
|
impl Display for ParamList {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let mut text = String::new();
|
||||||
|
text += "(";
|
||||||
|
for (idx, vtype) in self.0.iter().enumerate() {
|
||||||
|
if idx > 0 {
|
||||||
|
text += ", ";
|
||||||
|
}
|
||||||
|
text += &vtype.to_string();
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
write!(f, "{}", text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RuntimePanic {
|
pub enum RuntimePanic {
|
||||||
Fatal,
|
Fatal,
|
||||||
@ -109,4 +135,5 @@ pub enum RuntimePanic {
|
|||||||
InvalidHeapAddress,
|
InvalidHeapAddress,
|
||||||
ValueNotInitialized,
|
ValueNotInitialized,
|
||||||
InvalidTypeAssign,
|
InvalidTypeAssign,
|
||||||
|
InvalidFuncAddress,
|
||||||
}
|
}
|
||||||
|
22
src/main.rs
22
src/main.rs
@ -11,7 +11,7 @@ use std::path::Path;
|
|||||||
|
|
||||||
use compiler::Compiler;
|
use compiler::Compiler;
|
||||||
use parser::Parser;
|
use parser::Parser;
|
||||||
use vm::VirtualMachine;
|
use vm::{BuiltinFunctionDef, BuiltinFunctions, Value, VariableType, VirtualMachine};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let path = Path::new("reid_src/test.reid");
|
let path = Path::new("reid_src/test.reid");
|
||||||
@ -20,15 +20,29 @@ fn main() {
|
|||||||
eprintln!("Syntax error: {}", error);
|
eprintln!("Syntax error: {}", error);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
dbg!(&parsed);
|
//dbg!(&parsed);
|
||||||
let compiled = Compiler::from(parsed.unwrap()).compile();
|
|
||||||
|
let print = BuiltinFunctionDef::new(
|
||||||
|
"print",
|
||||||
|
vec![VariableType::TypeString],
|
||||||
|
Box::new(move |args| {
|
||||||
|
let Value::StringVal(string) = &args[0];
|
||||||
|
println!("{}", string);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
let builtin_functions = BuiltinFunctions(vec![print]);
|
||||||
|
|
||||||
|
let compiled = Compiler::from(parsed.unwrap())
|
||||||
|
.with_builtin_functions(builtin_functions.signatures())
|
||||||
|
.compile();
|
||||||
if let Err(error) = compiled {
|
if let Err(error) = compiled {
|
||||||
eprintln!("Compilation error: {}", error);
|
eprintln!("Compilation error: {}", error);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
dbg!(&compiled);
|
//dbg!(&compiled);
|
||||||
|
|
||||||
let mut vm = VirtualMachine::from(compiled.unwrap());
|
let mut vm = VirtualMachine::from(compiled.unwrap());
|
||||||
|
vm.add_builtin_functions(builtin_functions);
|
||||||
if let Err(error) = vm.run() {
|
if let Err(error) = vm.run() {
|
||||||
eprintln!("Runtime panic: {:#?}", error);
|
eprintln!("Runtime panic: {:#?}", error);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
|
@ -257,10 +257,6 @@ impl<'a> Expect<'a> {
|
|||||||
other,
|
other,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_expect<T: Into<String>>(&mut self, expectable: Expectable<T>) -> Expect {
|
|
||||||
self.parser.expect(expectable)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Expects<'a> {
|
pub struct Expects<'a> {
|
||||||
|
@ -74,6 +74,7 @@ impl Expression {
|
|||||||
Err(SyntaxError::ExpectedToken(parser.pos(), '}'))
|
Err(SyntaxError::ExpectedToken(parser.pos(), '}'))
|
||||||
}
|
}
|
||||||
} else if let Some(texts) = parser.expect_ident().and(Expectable::Static("(")).get() {
|
} else if let Some(texts) = parser.expect_ident().and(Expectable::Static("(")).get() {
|
||||||
|
let pos = parser.pos();
|
||||||
let name = texts.get(0).unwrap();
|
let name = texts.get(0).unwrap();
|
||||||
let mut arg_list = Vec::new();
|
let mut arg_list = Vec::new();
|
||||||
while {
|
while {
|
||||||
@ -95,7 +96,6 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} {}
|
} {}
|
||||||
let pos = parser.pos();
|
|
||||||
parser
|
parser
|
||||||
.expect_static(")")
|
.expect_static(")")
|
||||||
.get_or(SyntaxError::ExpectedToken(pos, ')'))?;
|
.get_or(SyntaxError::ExpectedToken(pos, ')'))?;
|
||||||
|
101
src/vm/functions.rs
Normal file
101
src/vm/functions.rs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
use super::{Value, VariableType};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FunctionSignature {
|
||||||
|
pub name: String,
|
||||||
|
pub parameters: Vec<VariableType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FunctionSignature {
|
||||||
|
pub fn new<T: Into<String>>(name: T, params: Vec<VariableType>) -> FunctionSignature {
|
||||||
|
FunctionSignature {
|
||||||
|
name: name.into(),
|
||||||
|
parameters: params,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for FunctionSignature {
|
||||||
|
fn eq(&self, other: &FunctionSignature) -> bool {
|
||||||
|
if self.name == other.name && self.parameters.len() == other.parameters.len() {
|
||||||
|
let mut found_difference = false;
|
||||||
|
for (idx, t) in self.parameters.iter().enumerate() {
|
||||||
|
if other.parameters[idx] != *t {
|
||||||
|
found_difference = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
!found_difference
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BuiltinFunctionDef> for FunctionSignature {
|
||||||
|
fn from(from: BuiltinFunctionDef) -> FunctionSignature {
|
||||||
|
from.signature
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum FunctionDef {
|
||||||
|
Builtin(BuiltinFunctionDef),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FunctionDef {
|
||||||
|
fn get_signature(&self) -> &FunctionSignature {
|
||||||
|
match self {
|
||||||
|
FunctionDef::Builtin(func) => &func.signature,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for FunctionDef {
|
||||||
|
fn eq(&self, other: &FunctionDef) -> bool {
|
||||||
|
self.get_signature() == other.get_signature()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<FunctionSignature> for FunctionDef {
|
||||||
|
fn eq(&self, other: &FunctionSignature) -> bool {
|
||||||
|
self.get_signature() == other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BuiltinFunctionDef {
|
||||||
|
pub signature: FunctionSignature,
|
||||||
|
pub function: Box<dyn Fn(Vec<Value>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuiltinFunctionDef {
|
||||||
|
pub fn new<T: Into<String>>(
|
||||||
|
name: T,
|
||||||
|
parameters: Vec<VariableType>,
|
||||||
|
func: Box<dyn Fn(Vec<Value>)>,
|
||||||
|
) -> BuiltinFunctionDef {
|
||||||
|
BuiltinFunctionDef {
|
||||||
|
signature: FunctionSignature {
|
||||||
|
name: name.into(),
|
||||||
|
parameters,
|
||||||
|
},
|
||||||
|
function: func,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BuiltinFunctions(pub Vec<BuiltinFunctionDef>);
|
||||||
|
|
||||||
|
impl BuiltinFunctions {
|
||||||
|
pub fn signatures(&self) -> Vec<FunctionSignature> {
|
||||||
|
let mut signatures = Vec::new();
|
||||||
|
for func in &self.0 {
|
||||||
|
signatures.push(func.signature.clone());
|
||||||
|
}
|
||||||
|
signatures
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BuiltinFunctions> for Vec<BuiltinFunctionDef> {
|
||||||
|
fn from(builtin: BuiltinFunctions) -> Self {
|
||||||
|
builtin.0
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,21 @@
|
|||||||
|
pub mod functions;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fmt;
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use super::compiler::{Command, CompiledReid, HeapID};
|
use super::compiler::{Command, CompiledReid, HeapID};
|
||||||
use super::errors::RuntimePanic;
|
use super::errors::RuntimePanic;
|
||||||
|
|
||||||
|
pub use functions::*;
|
||||||
|
|
||||||
pub struct VirtualMachine {
|
pub struct VirtualMachine {
|
||||||
registry_stack: Vec<[Option<Value>; 8]>,
|
registry_stack: Vec<[Option<Value>; 8]>,
|
||||||
registry: [Option<Value>; 8],
|
registry: [Option<Value>; 8],
|
||||||
|
|
||||||
stack: Vec<Value>,
|
stack: Vec<Value>,
|
||||||
heap: HashMap<HeapID, AllocatedVar>,
|
heap: HashMap<HeapID, AllocatedVar>,
|
||||||
|
functions: Vec<FunctionDef>,
|
||||||
|
|
||||||
position: usize,
|
position: usize,
|
||||||
compiled: CompiledReid,
|
compiled: CompiledReid,
|
||||||
@ -22,12 +29,19 @@ impl VirtualMachine {
|
|||||||
|
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
heap: HashMap::new(),
|
heap: HashMap::new(),
|
||||||
|
functions: Vec::new(),
|
||||||
|
|
||||||
position: 0,
|
position: 0,
|
||||||
compiled,
|
compiled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_builtin_functions<T: Into<Vec<BuiltinFunctionDef>>>(&mut self, list: T) {
|
||||||
|
for func in list.into() {
|
||||||
|
self.functions.push(FunctionDef::Builtin(func));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) -> Result<(), RuntimePanic> {
|
pub fn run(&mut self) -> Result<(), RuntimePanic> {
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
while error.is_none() {
|
while error.is_none() {
|
||||||
@ -60,19 +74,19 @@ impl VirtualMachine {
|
|||||||
match command {
|
match command {
|
||||||
Command::InitializeVariable(heapid, vtype) => {
|
Command::InitializeVariable(heapid, vtype) => {
|
||||||
self.heap.insert(heapid, AllocatedVar(vtype, None));
|
self.heap.insert(heapid, AllocatedVar(vtype, None));
|
||||||
dbg!("Initialized new variable to heap", &self.heap);
|
//dbg!("Initialized new variable to heap", &self.heap);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Command::BeginScope => {
|
Command::BeginScope => {
|
||||||
self.registry_stack.push(self.registry.clone());
|
self.registry_stack.push(self.registry.clone());
|
||||||
self.registry = Default::default();
|
self.registry = Default::default();
|
||||||
dbg!("Begun new scope");
|
//dbg!("Begun new scope");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Command::EndScope => {
|
Command::EndScope => {
|
||||||
if let Some(reg) = self.registry_stack.pop() {
|
if let Some(reg) = self.registry_stack.pop() {
|
||||||
self.registry = reg;
|
self.registry = reg;
|
||||||
dbg!("Scope ended");
|
//dbg!("Scope ended");
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimePanic::ScopeStackUnderflow)
|
Err(RuntimePanic::ScopeStackUnderflow)
|
||||||
@ -81,7 +95,7 @@ impl VirtualMachine {
|
|||||||
Command::Pop(regid) => {
|
Command::Pop(regid) => {
|
||||||
if let Some(val) = self.stack.pop() {
|
if let Some(val) = self.stack.pop() {
|
||||||
self.registry[regid] = Some(val);
|
self.registry[regid] = Some(val);
|
||||||
dbg!("Registry popped", regid, &self.stack, &self.registry);
|
//dbg!("Registry popped", regid, &self.stack, &self.registry);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimePanic::StackUnderflow)
|
Err(RuntimePanic::StackUnderflow)
|
||||||
@ -91,7 +105,7 @@ impl VirtualMachine {
|
|||||||
if let Some(reg) = &self.registry[regid] {
|
if let Some(reg) = &self.registry[regid] {
|
||||||
if self.stack.len() < usize::MAX {
|
if self.stack.len() < usize::MAX {
|
||||||
self.stack.push(reg.clone());
|
self.stack.push(reg.clone());
|
||||||
dbg!("Registry pushed", regid, &self.stack);
|
//dbg!("Registry pushed", regid, &self.stack);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimePanic::StackOverflow)
|
Err(RuntimePanic::StackOverflow)
|
||||||
@ -104,7 +118,7 @@ impl VirtualMachine {
|
|||||||
if let Some(reg) = &self.registry[regid] {
|
if let Some(reg) = &self.registry[regid] {
|
||||||
if let Some(var) = self.heap.get_mut(&heapid) {
|
if let Some(var) = self.heap.get_mut(&heapid) {
|
||||||
var.try_set(Some(reg.clone()))?;
|
var.try_set(Some(reg.clone()))?;
|
||||||
dbg!("Variable assigned", heapid, regid, &self.heap);
|
//dbg!("Variable assigned", heapid, regid, &self.heap);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimePanic::InvalidHeapAddress)
|
Err(RuntimePanic::InvalidHeapAddress)
|
||||||
@ -117,7 +131,7 @@ impl VirtualMachine {
|
|||||||
if let Some(var) = self.heap.get(&heapid) {
|
if let Some(var) = self.heap.get(&heapid) {
|
||||||
if let Some(val) = &var.1 {
|
if let Some(val) = &var.1 {
|
||||||
self.registry[regid] = Some(val.clone());
|
self.registry[regid] = Some(val.clone());
|
||||||
dbg!("Variable pushed to registry", heapid, regid, &self.registry);
|
//dbg!("Variable pushed to registry", heapid, regid, &self.registry);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimePanic::ValueNotInitialized)
|
Err(RuntimePanic::ValueNotInitialized)
|
||||||
@ -129,12 +143,32 @@ impl VirtualMachine {
|
|||||||
Command::StringLit(string) => {
|
Command::StringLit(string) => {
|
||||||
if self.stack.len() < usize::MAX {
|
if self.stack.len() < usize::MAX {
|
||||||
self.stack.push(Value::StringVal(string.clone()));
|
self.stack.push(Value::StringVal(string.clone()));
|
||||||
dbg!("String literal added to stack", string, &self.stack);
|
//dbg!("String literal added to stack", string, &self.stack);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimePanic::StackOverflow)
|
Err(RuntimePanic::StackOverflow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Command::FunctionCall(funcid) => {
|
||||||
|
if self.functions.len() <= funcid {
|
||||||
|
Err(RuntimePanic::InvalidFuncAddress)
|
||||||
|
} else {
|
||||||
|
match &self.functions[funcid] {
|
||||||
|
FunctionDef::Builtin(f) => {
|
||||||
|
let mut params = Vec::new();
|
||||||
|
for _ in 0..f.signature.parameters.len() {
|
||||||
|
if let Some(val) = self.stack.pop() {
|
||||||
|
params.push(val);
|
||||||
|
} else {
|
||||||
|
return Err(RuntimePanic::StackUnderflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(f.function)(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,14 +191,8 @@ impl AllocatedVar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
||||||
pub enum VariableType {
|
|
||||||
TypeString,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
enum Value {
|
pub enum Value {
|
||||||
StringVal(String),
|
StringVal(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,3 +203,16 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum VariableType {
|
||||||
|
TypeString,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for VariableType {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
VariableType::TypeString => "String".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user