From 0960516c4a6ea03c53a0b3559266a4933a5f1b6e Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Sun, 1 Mar 2026 16:11:57 -0600 Subject: [PATCH] Very minimal, but e2e hello world sort of working. --- Cargo.lock | 46 +++++-- Cargo.toml | 8 +- dm/Cargo.toml | 10 ++ dm/src/main.rs | 72 +++++++++++ dmc-lib/Cargo.toml | 1 + dmc-lib/src/asm/asm_block.rs | 4 + dmc-lib/src/asm/asm_function.rs | 13 ++ dmc-lib/src/asm/asm_instruction.rs | 63 +++++++++- dmc-lib/src/ast/integer_literal.rs | 6 +- dmc-lib/src/constants_table.rs | 8 ++ dmc-lib/src/ir/ir_expression.rs | 2 +- dmc-lib/src/lib.rs | 26 ++-- dmc-lib/src/parser.rs | 2 +- dmc-lib/src/symbol.rs | 6 +- dvm-lib/Cargo.toml | 6 + dvm-lib/src/instruction.rs | 21 ++++ dvm-lib/src/lib.rs | 2 + dvm-lib/src/vm/constant.rs | 31 +++++ dvm-lib/src/vm/function.rs | 34 ++++++ dvm-lib/src/vm/mod.rs | 187 +++++++++++++++++++++++++++++ dvm-lib/src/vm/value.rs | 14 +++ examples/hello.dm | 6 + 22 files changed, 530 insertions(+), 38 deletions(-) create mode 100644 dm/Cargo.toml create mode 100644 dm/src/main.rs create mode 100644 dvm-lib/Cargo.toml create mode 100644 dvm-lib/src/instruction.rs create mode 100644 dvm-lib/src/lib.rs create mode 100644 dvm-lib/src/vm/constant.rs create mode 100644 dvm-lib/src/vm/function.rs create mode 100644 dvm-lib/src/vm/mod.rs create mode 100644 dvm-lib/src/vm/value.rs create mode 100644 examples/hello.dm diff --git a/Cargo.lock b/Cargo.lock index 1780281..e2d9d37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,9 +86,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.23" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" dependencies = [ "clap_builder", "clap_derive", @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" dependencies = [ "anstream", "anstyle", @@ -108,9 +108,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck", "proc-macro2", @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] name = "codespan-reporting" @@ -135,6 +135,17 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + [[package]] name = "colorchoice" version = "1.0.3" @@ -186,7 +197,7 @@ version = "0.1.0" dependencies = [ "ast-generator", "clap", - "codespan-reporting", + "codespan-reporting 0.12.0", "cst-test-generator", "indoc", "log", @@ -204,9 +215,26 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dm" +version = "0.1.0" +dependencies = [ + "clap", + "codespan-reporting 0.13.1", + "dmc-lib", + "dvm-lib", +] + [[package]] name = "dmc-lib" version = "0.1.0" +dependencies = [ + "dvm-lib", +] + +[[package]] +name = "dvm-lib" +version = "0.1.0" [[package]] name = "encoding_rs" diff --git a/Cargo.toml b/Cargo.toml index 0236f76..08f07ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,9 @@ name = "deimos" version = "0.1.0" edition = "2021" -[[bin]] -name = "dm" -path = "src/bin/dvm/main.rs" +#[[bin]] +#name = "dm" +#path = "src/bin/dvm/main.rs" [[bin]] name = "dmc" @@ -25,4 +25,4 @@ cst-test-generator = { path = "cst-test-generator" } [workspace] resolver = "3" -members = ["ast-generator", "cst-test-generator", "dmc-lib"] +members = ["ast-generator", "cst-test-generator", "dm", "dmc-lib", "dvm-lib"] diff --git a/dm/Cargo.toml b/dm/Cargo.toml new file mode 100644 index 0000000..e70abb9 --- /dev/null +++ b/dm/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "dm" +version = "0.1.0" +edition = "2024" + +[dependencies] +dmc-lib = { path = "../dmc-lib" } +dvm-lib = { path = "../dvm-lib" } +clap = { version = "4.5.60", features = ["derive"] } +codespan-reporting = "0.13.1" \ No newline at end of file diff --git a/dm/src/main.rs b/dm/src/main.rs new file mode 100644 index 0000000..bfff713 --- /dev/null +++ b/dm/src/main.rs @@ -0,0 +1,72 @@ +use clap::Parser; +use dmc_lib::constants_table::ConstantsTable; +use dmc_lib::diagnostic::Diagnostic; +use dmc_lib::parser::parse_compilation_unit; +use dmc_lib::symbol_table::SymbolTable; +use dvm_lib::vm::constant::{Constant, StringConstant}; +use dvm_lib::vm::{DvmContext, DvmState, call}; +use std::path::PathBuf; +use std::rc::Rc; + +#[derive(Debug, Parser)] +#[command(name = "dm", about = "Deimos", version = "0.1.0", long_about = None)] +struct Cli { + script: PathBuf, + + #[arg(long)] + show_asm: bool, +} + +fn main() { + let args = Cli::parse(); + let input = std::fs::read_to_string(&args.script).unwrap(); + + let mut compilation_unit = parse_compilation_unit(&input); + let mut symbol_table = SymbolTable::new(); + + let gather_names_diagnostics = compilation_unit.gather_declared_names(&mut symbol_table); + check_and_report_diagnostics(&gather_names_diagnostics); + + let name_usages_diagnostics = compilation_unit.check_name_usages(&symbol_table); + check_and_report_diagnostics(&name_usages_diagnostics); + + let type_check_diagnostics = compilation_unit.type_check(&symbol_table); + check_and_report_diagnostics(&type_check_diagnostics); + + let mut constants_table = ConstantsTable::new(); + let asm_functions = compilation_unit.assemble(&symbol_table, &mut constants_table); + + if args.show_asm { + for asm_function in &asm_functions { + println!("{:?}", asm_function); + } + } + + let mut dvm_context = DvmContext::new(); + + for asm_function in &asm_functions { + let function = asm_function.dvm(); + dvm_context.add_function(function); + } + + for (name, content) in &constants_table.string_constants() { + dvm_context.add_constant(Constant::String(StringConstant::new( + Rc::from(name.clone()), + content.as_str(), + ))); + } + + let mut dvm_state = DvmState::new(); + + let result = call(&dvm_context, &mut dvm_state, "main", vec![]); + println!("{:?}", result); +} + +fn check_and_report_diagnostics(diagnostics: &[Diagnostic]) { + if !diagnostics.is_empty() { + for diagnostic in diagnostics { + println!("{:?}", diagnostic); + } + std::process::exit(1); + } +} diff --git a/dmc-lib/Cargo.toml b/dmc-lib/Cargo.toml index a31e708..069df7b 100644 --- a/dmc-lib/Cargo.toml +++ b/dmc-lib/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2024" [dependencies] +dvm-lib = { path = "../dvm-lib" } diff --git a/dmc-lib/src/asm/asm_block.rs b/dmc-lib/src/asm/asm_block.rs index 4291e22..e0e3123 100644 --- a/dmc-lib/src/asm/asm_block.rs +++ b/dmc-lib/src/asm/asm_block.rs @@ -13,4 +13,8 @@ impl AsmBlock { instructions, } } + + pub fn instructions(&self) -> &[AsmInstruction] { + &self.instructions + } } diff --git a/dmc-lib/src/asm/asm_function.rs b/dmc-lib/src/asm/asm_function.rs index 46e20f2..6ee7ed7 100644 --- a/dmc-lib/src/asm/asm_function.rs +++ b/dmc-lib/src/asm/asm_function.rs @@ -1,4 +1,6 @@ use crate::asm::asm_block::AsmBlock; +use crate::asm::asm_instruction::AsmInstruction; +use dvm_lib::vm::function::Function; #[derive(Debug)] pub struct AsmFunction { @@ -13,4 +15,15 @@ impl AsmFunction { blocks, } } + + pub fn dvm(&self) -> Function { + // very naive impl + let dvm_instructions = self + .blocks + .iter() + .flat_map(|block| block.instructions().iter().map(AsmInstruction::dvm)) + .collect::>(); + + Function::new(&self.name, dvm_instructions, 16) + } } diff --git a/dmc-lib/src/asm/asm_instruction.rs b/dmc-lib/src/asm/asm_instruction.rs index 6436460..a3706a3 100644 --- a/dmc-lib/src/asm/asm_instruction.rs +++ b/dmc-lib/src/asm/asm_instruction.rs @@ -1,3 +1,6 @@ +use dvm_lib::instruction::Instruction; +use std::rc::Rc; + #[derive(Debug)] pub enum AsmInstruction { Move(Move), @@ -7,11 +10,25 @@ pub enum AsmInstruction { LoadConstant(LoadConstant), } +impl AsmInstruction { + pub fn dvm(&self) -> Instruction { + match self { + AsmInstruction::Move(asm_move) => asm_move.dvm(), + AsmInstruction::Push(push) => push.dvm(), + AsmInstruction::Pop(pop) => pop.dvm(), + AsmInstruction::InvokePlatformStatic(invoke_platform_static) => { + invoke_platform_static.dvm() + } + AsmInstruction::LoadConstant(load_constant) => load_constant.dvm(), + } + } +} + #[derive(Debug)] pub enum Operand { - IntegerLiteral(i64), + IntegerLiteral(i32), Register(usize), - StackFrameOffset(usize), + StackFrameOffset(isize), } #[derive(Debug)] @@ -27,6 +44,18 @@ impl Move { destination_register, } } + + pub fn dvm(&self) -> Instruction { + match self.source { + Operand::IntegerLiteral(i) => Instruction::MoveInt(i, self.destination_register), + Operand::Register(register) => { + Instruction::MoveRegister(register, self.destination_register) + } + Operand::StackFrameOffset(offset) => { + Instruction::MoveStackFrameOffset(offset, self.destination_register) + } + } + } } #[derive(Debug)] @@ -38,19 +67,37 @@ impl Push { pub fn new(source: Operand) -> Self { Self { source } } + + pub fn dvm(&self) -> Instruction { + match self.source { + Operand::IntegerLiteral(i) => Instruction::PushInt(i), + Operand::Register(register) => Instruction::PushRegister(register), + Operand::StackFrameOffset(offset) => Instruction::PushStackFrameOffset(offset), + } + } } #[derive(Debug)] pub struct Pop { - destination_register: usize, + destination_register: Option, } impl Pop { pub fn new(destination_register: usize) -> Self { Self { - destination_register, + destination_register: Some(destination_register), } } + + pub fn empty() -> Self { + Self { + destination_register: None, + } + } + + pub fn dvm(&self) -> Instruction { + Instruction::Pop(self.destination_register) + } } #[derive(Debug)] @@ -62,6 +109,10 @@ impl InvokePlatformStatic { pub fn new(name: &str) -> Self { Self { name: name.into() } } + + pub fn dvm(&self) -> Instruction { + Instruction::InvokePlatformStatic(Rc::from(self.name.clone())) + } } #[derive(Debug)] @@ -77,4 +128,8 @@ impl LoadConstant { destination_register, } } + + pub fn dvm(&self) -> Instruction { + Instruction::LoadStringConstant(Rc::from(self.name.clone()), self.destination_register) + } } diff --git a/dmc-lib/src/ast/integer_literal.rs b/dmc-lib/src/ast/integer_literal.rs index 6cec042..7a3ed2d 100644 --- a/dmc-lib/src/ast/integer_literal.rs +++ b/dmc-lib/src/ast/integer_literal.rs @@ -3,19 +3,19 @@ use crate::ir::ir_expression::IrExpression; use crate::source_range::SourceRange; pub struct IntegerLiteral { - value: i64, + value: i32, source_range: SourceRange, } impl IntegerLiteral { - pub fn new(value: i64, source_range: SourceRange) -> Self { + pub fn new(value: i32, source_range: SourceRange) -> Self { Self { value, source_range, } } - pub fn value(&self) -> i64 { + pub fn value(&self) -> i32 { self.value } diff --git a/dmc-lib/src/constants_table.rs b/dmc-lib/src/constants_table.rs index 88199f9..1ab1adb 100644 --- a/dmc-lib/src/constants_table.rs +++ b/dmc-lib/src/constants_table.rs @@ -19,4 +19,12 @@ impl ConstantsTable { self.strings_to_names.insert(s.into(), name.clone()); name } + + pub fn string_constants(&self) -> HashMap { + let mut constants = HashMap::new(); + self.strings_to_names.iter().for_each(|(content, name)| { + constants.insert(name.clone(), content.clone()); + }); + constants + } } diff --git a/dmc-lib/src/ir/ir_expression.rs b/dmc-lib/src/ir/ir_expression.rs index 6a604a6..eb24c62 100644 --- a/dmc-lib/src/ir/ir_expression.rs +++ b/dmc-lib/src/ir/ir_expression.rs @@ -6,6 +6,6 @@ use crate::ir::ir_variable::IrVariable; pub enum IrExpression { Call(IrCall), Constant(IrConstant), - IntegerLiteral(i64), + IntegerLiteral(i32), Variable(IrVariable), } diff --git a/dmc-lib/src/lib.rs b/dmc-lib/src/lib.rs index c6b8fd4..5578421 100644 --- a/dmc-lib/src/lib.rs +++ b/dmc-lib/src/lib.rs @@ -1,13 +1,13 @@ -mod asm; -mod ast; -mod constants_table; -mod diagnostic; -mod ir; -mod lexer; -mod parser; -mod scope; -mod source_range; -mod symbol; -mod symbol_table; -mod token; -mod type_info; +pub mod asm; +pub mod ast; +pub mod constants_table; +pub mod diagnostic; +pub mod ir; +pub mod lexer; +pub mod parser; +pub mod scope; +pub mod source_range; +pub mod symbol; +pub mod symbol_table; +pub mod token; +pub mod type_info; diff --git a/dmc-lib/src/parser.rs b/dmc-lib/src/parser.rs index af0d8d7..8dc568c 100644 --- a/dmc-lib/src/parser.rs +++ b/dmc-lib/src/parser.rs @@ -181,7 +181,7 @@ impl<'a> Parser<'a> { let source_range = SourceRange::new(current.start(), current.end()); self.advance(); Expression::IntegerLiteral(IntegerLiteral::new( - i64::from_str(raw).unwrap(), + i32::from_str(raw).unwrap(), source_range, )) } diff --git a/dmc-lib/src/symbol.rs b/dmc-lib/src/symbol.rs index db2365f..597eb84 100644 --- a/dmc-lib/src/symbol.rs +++ b/dmc-lib/src/symbol.rs @@ -35,7 +35,7 @@ impl FunctionSymbol { pub struct ParameterSymbol { name: Rc, type_info: TypeInfo, - stack_frame_offset: Option, + stack_frame_offset: Option, } impl ParameterSymbol { @@ -59,11 +59,11 @@ impl ParameterSymbol { &self.type_info } - pub fn set_stack_frame_offset(&mut self, offset: usize) { + pub fn set_stack_frame_offset(&mut self, offset: isize) { self.stack_frame_offset = Some(offset); } - pub fn stack_frame_offset(&self) -> usize { + pub fn stack_frame_offset(&self) -> isize { self.stack_frame_offset.unwrap() } } diff --git a/dvm-lib/Cargo.toml b/dvm-lib/Cargo.toml new file mode 100644 index 0000000..25e7110 --- /dev/null +++ b/dvm-lib/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "dvm-lib" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/dvm-lib/src/instruction.rs b/dvm-lib/src/instruction.rs new file mode 100644 index 0000000..1e0b26e --- /dev/null +++ b/dvm-lib/src/instruction.rs @@ -0,0 +1,21 @@ +use std::rc::Rc; + +pub type Register = usize; +pub type ConstantName = Rc; +pub type FunctionName = Rc; + +pub enum Instruction { + MoveRegister(Register, Register), + MoveInt(i32, Register), + MoveStackFrameOffset(isize, Register), + + PushRegister(Register), + PushInt(i32), + PushStackFrameOffset(isize), + + InvokePlatformStatic(FunctionName), + + LoadStringConstant(ConstantName, Register), + + Pop(Option), +} diff --git a/dvm-lib/src/lib.rs b/dvm-lib/src/lib.rs new file mode 100644 index 0000000..b7c1352 --- /dev/null +++ b/dvm-lib/src/lib.rs @@ -0,0 +1,2 @@ +pub mod instruction; +pub mod vm; diff --git a/dvm-lib/src/vm/constant.rs b/dvm-lib/src/vm/constant.rs new file mode 100644 index 0000000..d45717a --- /dev/null +++ b/dvm-lib/src/vm/constant.rs @@ -0,0 +1,31 @@ +use std::rc::Rc; + +pub enum Constant { + String(StringConstant), +} + +pub struct StringConstant { + name: Rc, + content: Rc, +} + +impl StringConstant { + pub fn new(name: Rc, content: &str) -> Self { + Self { + name, + content: content.into(), + } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn name_owned(&self) -> Rc { + self.name.clone() + } + + pub fn content_owned(&self) -> Rc { + self.content.clone() + } +} diff --git a/dvm-lib/src/vm/function.rs b/dvm-lib/src/vm/function.rs new file mode 100644 index 0000000..d682465 --- /dev/null +++ b/dvm-lib/src/vm/function.rs @@ -0,0 +1,34 @@ +use crate::instruction::Instruction; +use std::rc::Rc; + +pub struct Function { + name: Rc, + instructions: Vec, + register_count: usize, +} + +impl Function { + pub fn new(name: &str, instructions: Vec, register_count: usize) -> Self { + Self { + name: name.into(), + instructions, + register_count, + } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn name_owned(&self) -> Rc { + self.name.clone() + } + + pub fn instructions(&self) -> &Vec { + &self.instructions + } + + pub fn register_count(&self) -> usize { + self.register_count + } +} diff --git a/dvm-lib/src/vm/mod.rs b/dvm-lib/src/vm/mod.rs new file mode 100644 index 0000000..d2d1cb4 --- /dev/null +++ b/dvm-lib/src/vm/mod.rs @@ -0,0 +1,187 @@ +use crate::instruction::Instruction; +use crate::vm::constant::Constant; +use crate::vm::function::Function; +use crate::vm::value::Value; +use std::collections::HashMap; +use std::rc::Rc; + +pub mod constant; +pub mod function; +pub mod value; + +pub struct DvmContext { + functions: HashMap, Function>, + constants: HashMap, Constant>, +} + +impl DvmContext { + pub fn new() -> Self { + Self { + functions: HashMap::new(), + constants: HashMap::new(), + } + } + + pub fn add_function(&mut self, function: Function) { + self.functions.insert(function.name_owned(), function); + } + + pub fn constants(&self) -> &HashMap, Constant> { + &self.constants + } + + pub fn add_constant(&mut self, constant: Constant) { + match &constant { + Constant::String(string_constant) => { + self.constants + .insert(string_constant.name_owned(), constant); + } + } + } +} + +pub struct DvmState { + stack: Vec, + registers: Vec, + ip: usize, + fp: usize, +} + +impl DvmState { + pub fn new() -> Self { + Self { + stack: vec![], + registers: vec![], + ip: 0, + fp: 0, + } + } + + pub fn stack(&self) -> &Vec { + &self.stack + } + + pub fn stack_mut(&mut self) -> &mut Vec { + &mut self.stack + } + + pub fn registers(&self) -> &Vec { + &self.registers + } + + pub fn registers_mut(&mut self) -> &mut Vec { + &mut self.registers + } + + pub fn ensure_registers(&mut self, count: usize) { + self.registers.resize_with(count, Default::default); + } + + pub fn ip(&self) -> usize { + self.ip + } + + pub fn increment_ip(&mut self) { + self.ip += 1; + } + + pub fn fp(&self) -> usize { + self.fp + } + + pub fn set_fp(&mut self, fp: usize) { + self.fp = fp; + } +} + +pub fn call( + context: &DvmContext, + state: &mut DvmState, + function_name: &str, + arguments: Vec, +) -> Option { + let function = context + .functions + .get(function_name) + .expect(&format!("Function {} not found", function_name)); + + let instructions = function.instructions(); + state.ensure_registers(function.register_count()); + + // put each arg on the stack + for argument in arguments { + state.stack_mut().push(argument); + } + + while state.ip() < instructions.len() { + let instruction = &instructions[state.ip()]; + match instruction { + /* Move instructions */ + Instruction::MoveRegister(source, destination) => { + // copy value from one register to another register + let value = state.registers()[*source].clone(); + state.registers_mut()[*destination] = value; + } + Instruction::MoveInt(value, destination) => { + state.registers_mut()[*destination] = Value::Int(*value); + } + Instruction::MoveStackFrameOffset(offset, destination) => { + // copy a value offset from the current frame pointer (fp) to a register + let value_index = state + .fp() + .checked_add_signed(*offset) + .expect("Overflow when adding offset to fp"); + let value = state.stack()[value_index].clone(); + state.registers_mut()[*destination] = value; + } + + /* Push instructions */ + Instruction::PushRegister(source) => { + // copy a value from a register to the top of the stack + let value = state.registers()[*source].clone(); + state.stack_mut().push(value); + } + Instruction::PushInt(value) => { + state.stack_mut().push(Value::Int(*value)); + } + Instruction::PushStackFrameOffset(offset) => { + // copy a value from somewhere on the stack to the top of the stack + let value_index = state + .fp() + .checked_add_signed(*offset) + .expect("Overflow when adding offset to fp"); + let value = state.stack()[value_index].clone(); + state.stack_mut().push(value); + } + + /* Invoke instructions */ + Instruction::InvokePlatformStatic(function_name) => { + if function_name.as_ref() == "println" { + println!("{:?}", state.stack()); + println!("{:?}", state.registers()); + } + } + + /* Load constant instructions */ + Instruction::LoadStringConstant(constant_name, destination) => { + let constant = &context.constants()[constant_name]; + match constant { + Constant::String(string_constant) => { + state.registers_mut()[*destination] = + Value::String(string_constant.content_owned()); + } + } + } + + /* Pop instructions */ + Instruction::Pop(maybe_register) => { + let value = state.stack_mut().pop().unwrap(); + if let Some(register) = maybe_register { + state.registers_mut()[*register] = value; + } + } + } + state.increment_ip(); + } + None +} diff --git a/dvm-lib/src/vm/value.rs b/dvm-lib/src/vm/value.rs new file mode 100644 index 0000000..9c55ae0 --- /dev/null +++ b/dvm-lib/src/vm/value.rs @@ -0,0 +1,14 @@ +use std::rc::Rc; + +#[derive(Clone, Debug)] +pub enum Value { + Int(i32), + String(Rc), + Null, +} + +impl Default for Value { + fn default() -> Value { + Value::Null + } +} diff --git a/examples/hello.dm b/examples/hello.dm new file mode 100644 index 0000000..65091d4 --- /dev/null +++ b/examples/hello.dm @@ -0,0 +1,6 @@ +fn println() end + +fn main() + let x = "Hello, World!" + println(x) +end \ No newline at end of file