Work on vm and DvmValues and DmTypes. Added pest to get parser off the ground.
This commit is contained in:
parent
d99ccf8807
commit
cccbc6d819
398
Cargo.lock
generated
398
Cargo.lock
generated
@ -2,6 +2,404 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deimos"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.167"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
@ -12,3 +12,6 @@ name = "dm"
|
||||
path = "src/bin/dvm/main.rs"
|
||||
|
||||
[dependencies]
|
||||
pest = "2.7.14"
|
||||
clap = { version = "4.5.23", features = ["derive"] }
|
||||
pest_derive = "2.7.14"
|
||||
|
@ -1,11 +1,22 @@
|
||||
use deimos::vm::op_codes::{add_mov_int, add_platform_call_to};
|
||||
use deimos::vm::DmVirtualMachine;
|
||||
use deimos::vm::dvm_value::DvmValue;
|
||||
|
||||
fn main() {
|
||||
// TODO:
|
||||
// - write a single module with a main() fn which takes cli args
|
||||
// - call the main fn
|
||||
|
||||
let mut code: Vec<u8> = Vec::new();
|
||||
add_mov_int(&mut code, 0, 42);
|
||||
add_platform_call_to(&mut code, &String::from("std::core::print"), 0, 1, &vec![0u8]);
|
||||
add_mov_int(&mut code, 0, 0x2a); // 42
|
||||
add_platform_call_to(
|
||||
&mut code,
|
||||
&String::from("std::core::println"),
|
||||
0,
|
||||
1,
|
||||
&vec![0u8],
|
||||
);
|
||||
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||
vm.run(&mut code);
|
||||
println!()
|
||||
}
|
||||
vm.run_raw(&mut code);
|
||||
vm.call_by_fqn("default::main", vec![DvmValue::Unit; 0]); // will throw
|
||||
}
|
||||
|
37
src/parser/deimos.pest
Normal file
37
src/parser/deimos.pest
Normal file
@ -0,0 +1,37 @@
|
||||
compilation_unit = { SOI ~ namespace? ~ declaration* ~ EOI }
|
||||
namespace = { "ns" ~ fqn }
|
||||
|
||||
fqn = { identifier ~ ( "::" ~ fqn )* }
|
||||
identifier = @{ identifier_start_char ~ identifier_char* }
|
||||
identifier_start_char = { 'a'..'z' | 'A'..'Z' | "_" }
|
||||
identifier_char = { 'a'..'z' | 'A'..'Z' | '0'..'9' | "_" }
|
||||
|
||||
declaration = { "decl"? ~ "pub"? ~ ( interface | module | property | function ) }
|
||||
|
||||
interface = { "int" ~ identifier ~ generics_declaration? ~ interface_extends_list? ~ "{" ~ declaration* ~ "}"}
|
||||
interface_extends_list = { ":" ~ type ~ ( "+" ~ type )* }
|
||||
|
||||
module = { "mod" ~ identifier ~ "{" ~ declaration* ~ "}" }
|
||||
|
||||
property = { identifier ~ ":" ~ type }
|
||||
|
||||
function = { "fn" ~ generics_declaration? ~ identifier ~ "(" ~ args_list? ~ ")" ~ ( ":" ~ type )? ~ ( "{" ~ "}" )? }
|
||||
|
||||
function_equals_body = { "=" ~ expression }
|
||||
function_body = { "{" ~ "}" }
|
||||
|
||||
type = { identifier ~ generics_declaration? }
|
||||
generics_declaration = { "<" ~ identifier ~ ( "," ~ identifier )* ~ ">"}
|
||||
|
||||
args_list = { arg ~ ( "," ~ arg )* }
|
||||
arg = { identifier ~ ( ":" ~ "..."? ~ type )? }
|
||||
|
||||
expression = { literal }
|
||||
|
||||
literal = { number_literal }
|
||||
|
||||
number_literal = { int_literal }
|
||||
|
||||
int_literal = { '0'..'9'+ }
|
||||
|
||||
WHITESPACE = { " " | "\t" | "\n" | "\r" }
|
@ -2,7 +2,17 @@ mod types;
|
||||
|
||||
use crate::lexer::Token;
|
||||
use crate::parser::types::AstNode;
|
||||
use pest::Parser;
|
||||
use pest_derive::Parser;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[grammar = "parser/deimos.pest"]
|
||||
struct DeimosParser;
|
||||
|
||||
pub fn parse(tokens: &Vec<Token>) -> Result<AstNode, String> {
|
||||
let p = DeimosParser::parse(Rule::compilation_unit, "ns std::core")
|
||||
.expect("unable to parse")
|
||||
.next()
|
||||
.unwrap();
|
||||
todo!()
|
||||
}
|
||||
|
45
src/vm/dm_type.rs
Normal file
45
src/vm/dm_type.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use std::rc::Rc;
|
||||
use crate::vm::object_type::DmObjectType;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DmType {
|
||||
Primitive(DmPrimitiveType),
|
||||
Object(Rc<DmObjectType>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DmPrimitiveType {
|
||||
Byte,
|
||||
Int,
|
||||
Long,
|
||||
Double,
|
||||
Boolean,
|
||||
Pointer(Rc<DmType>),
|
||||
ByteArray(usize),
|
||||
IntArray(usize),
|
||||
LongArray(usize),
|
||||
DoubleArray(usize),
|
||||
BooleanArray(usize),
|
||||
PointerArray(usize, Rc<DmType>),
|
||||
Unit,
|
||||
}
|
||||
|
||||
impl DmPrimitiveType {
|
||||
pub fn size_in_bytes(&self) -> usize {
|
||||
match self {
|
||||
DmPrimitiveType::Byte => size_of::<u8>(),
|
||||
DmPrimitiveType::Int => size_of::<i32>(),
|
||||
DmPrimitiveType::Long => size_of::<i64>(),
|
||||
DmPrimitiveType::Double => size_of::<f64>(),
|
||||
DmPrimitiveType::Boolean => size_of::<bool>(),
|
||||
DmPrimitiveType::Pointer(_) => size_of::<usize>(),
|
||||
DmPrimitiveType::ByteArray(length) => *length * size_of::<u8>(),
|
||||
DmPrimitiveType::IntArray(length) => *length * size_of::<i32>(),
|
||||
DmPrimitiveType::LongArray(length) => *length * size_of::<i64>(),
|
||||
DmPrimitiveType::DoubleArray(length) => *length * size_of::<f64>(),
|
||||
DmPrimitiveType::BooleanArray(length) => *length * size_of::<bool>(),
|
||||
DmPrimitiveType::PointerArray(length, _) => *length * size_of::<usize>(),
|
||||
DmPrimitiveType::Unit => todo!("Need to determine size of Unit... is it dependent on the size of the thing which is Unit?")
|
||||
}
|
||||
}
|
||||
}
|
16
src/vm/dvm_value.rs
Normal file
16
src/vm/dvm_value.rs
Normal file
@ -0,0 +1,16 @@
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum DvmValue {
|
||||
Byte(u8),
|
||||
Int(i32),
|
||||
Long(i64),
|
||||
Double(f64),
|
||||
Boolean(bool),
|
||||
Pointer(Box<DvmValue>),
|
||||
ByteArray(Vec<u8>),
|
||||
IntArray(Vec<i32>),
|
||||
LongArray(Vec<i64>),
|
||||
DoubleArray(Vec<f64>),
|
||||
BooleanArray(Vec<bool>),
|
||||
PointerArray(Vec<Box<DvmValue>>),
|
||||
Unit,
|
||||
}
|
147
src/vm/mem.rs
147
src/vm/mem.rs
@ -1,78 +1,95 @@
|
||||
use crate::vm::types::{DmImplementation, DmProperty, DmType};
|
||||
use crate::vm::values::DmValue;
|
||||
use crate::vm::dm_type::DmPrimitiveType;
|
||||
use crate::vm::dvm_value::DvmValue;
|
||||
use crate::vm::object_type::DmProperty;
|
||||
use crate::vm::object_type::DmImplementation;
|
||||
use std::alloc::Layout;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct DmAllocObject<'a> {
|
||||
pub struct DmAllocObject {
|
||||
pub data: *mut u8,
|
||||
pub size: usize,
|
||||
pub layout: Layout,
|
||||
pub object_type: &'a DmImplementation<'a>,
|
||||
pub implementation: Rc<DmImplementation>,
|
||||
}
|
||||
|
||||
pub unsafe fn get_property_value(dm_property: &DmProperty, dm_property_object: &DmAllocObject) -> DmValue {
|
||||
let mut data: Vec<u8> = Vec::with_capacity(dm_property.dm_type.size_in_bytes());
|
||||
for i in dm_property.data_offset..(dm_property.data_offset + dm_property.dm_type.size_in_bytes()) {
|
||||
data.push(dm_property_object.data.offset(i as isize).read());
|
||||
pub unsafe fn get_property_value(
|
||||
dm_property: &DmProperty,
|
||||
self_object: &DmAllocObject,
|
||||
) -> DvmValue {
|
||||
let data_size = dm_property.primitive_type.size_in_bytes();
|
||||
let mut raw_data: Vec<u8> = Vec::with_capacity(data_size);
|
||||
for i in dm_property.data_offset..(dm_property.data_offset + data_size) {
|
||||
raw_data.push(self_object.data.offset(i as isize).read());
|
||||
}
|
||||
match dm_property.dm_type {
|
||||
DmType::Byte => {
|
||||
DmValue::DmByte(data[0])
|
||||
match dm_property.primitive_type.as_ref() {
|
||||
DmPrimitiveType::Byte => DvmValue::Byte(raw_data[0]),
|
||||
DmPrimitiveType::Int => DvmValue::Int(i32::from_ne_bytes(
|
||||
raw_data[0..data_size].try_into().unwrap(),
|
||||
)),
|
||||
DmPrimitiveType::Long => DvmValue::Long(i64::from_ne_bytes(
|
||||
raw_data[0..data_size].try_into().unwrap(),
|
||||
)),
|
||||
DmPrimitiveType::Double => DvmValue::Double(f64::from_ne_bytes(
|
||||
raw_data[0..data_size].try_into().unwrap(),
|
||||
)),
|
||||
DmPrimitiveType::Boolean => DvmValue::Boolean(raw_data[0] == 1),
|
||||
DmPrimitiveType::Pointer(_) => {
|
||||
// read the pointer's (address) value
|
||||
let address = usize::from_ne_bytes(raw_data[0..data_size].try_into().unwrap());
|
||||
DvmValue::Pointer(Box::from_raw(address as *mut DvmValue))
|
||||
}
|
||||
DmType::Int => {
|
||||
DmValue::DmInt(i32::from_ne_bytes(data[0..4].try_into().unwrap()))
|
||||
DmPrimitiveType::ByteArray(_) => DvmValue::ByteArray(raw_data),
|
||||
DmPrimitiveType::IntArray(length) => DvmValue::IntArray(read_i32_array(&raw_data, *length)),
|
||||
DmPrimitiveType::LongArray(length) => {
|
||||
DvmValue::LongArray(read_i64_array(&raw_data, *length))
|
||||
}
|
||||
DmType::Long => {
|
||||
DmValue::DmLong(i64::from_ne_bytes(data[0..8].try_into().unwrap()))
|
||||
DmPrimitiveType::DoubleArray(length) => {
|
||||
DvmValue::DoubleArray(read_f64_array(&raw_data, *length))
|
||||
}
|
||||
DmType::Double => {
|
||||
DmValue::DmDouble(f64::from_ne_bytes(data[0..8].try_into().unwrap()))
|
||||
}
|
||||
DmType::Boolean => {
|
||||
DmValue::DmBoolean(i32::from_ne_bytes(data[0..4].try_into().unwrap()) != 0)
|
||||
}
|
||||
DmType::ObjectPointer(_) => {
|
||||
DmValue::DmPointer(usize::from_ne_bytes(data[0..8].try_into().unwrap()) as *mut DmAllocObject)
|
||||
}
|
||||
DmType::ByteArray(_) => {
|
||||
DmValue::DmByteArray(data)
|
||||
}
|
||||
DmType::IntArray(length) => {
|
||||
let mut result = Vec::with_capacity(length);
|
||||
for i in 0..length {
|
||||
result.push(i32::from_ne_bytes(data[(i * 4)..(i * 4 + 4)].try_into().unwrap()));
|
||||
}
|
||||
DmValue::DmIntArray(result)
|
||||
}
|
||||
DmType::LongArray(length) => {
|
||||
let mut result = Vec::with_capacity(length);
|
||||
for i in 0..length {
|
||||
result.push(i64::from_ne_bytes(data[i * 8..(i * 8 + 8)].try_into().unwrap()));
|
||||
}
|
||||
DmValue::DmLongArray(result)
|
||||
}
|
||||
DmType::DoubleArray(length) => {
|
||||
let mut result = Vec::with_capacity(length);
|
||||
for i in 0..length {
|
||||
result.push(f64::from_ne_bytes(data[i * 8..(i * 8 + 8)].try_into().unwrap()));
|
||||
}
|
||||
DmValue::DmDoubleArray(result)
|
||||
}
|
||||
DmType::BooleanArray(length) => {
|
||||
let mut result = Vec::with_capacity(length);
|
||||
for i in 0..length {
|
||||
result.push(i32::from_ne_bytes(data[(i * 4)..(i * 4 + 4)].try_into().unwrap()) != 0);
|
||||
}
|
||||
DmValue::DmBooleanArray(result)
|
||||
}
|
||||
DmType::ObjectPointerArray(length, _) => {
|
||||
let mut result = Vec::with_capacity(length);
|
||||
for i in 0..length {
|
||||
result.push(usize::from_ne_bytes(data[(i * 8)..(i * 8 + 8)].try_into().unwrap()) as *mut DmAllocObject);
|
||||
}
|
||||
DmValue::DmPointerArray(result)
|
||||
}
|
||||
DmType::Unit => {
|
||||
DmValue::DmUnit
|
||||
DmPrimitiveType::BooleanArray(length) => {
|
||||
DvmValue::BooleanArray(read_bool_array(&raw_data))
|
||||
}
|
||||
DmPrimitiveType::PointerArray(length, _) => DvmValue::PointerArray(
|
||||
read_usize_array(&raw_data, *length)
|
||||
.iter()
|
||||
.map(|raw_usize| Box::from_raw(*raw_usize as *mut DvmValue))
|
||||
.collect(),
|
||||
),
|
||||
DmPrimitiveType::Unit => DvmValue::Unit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! read_array {
|
||||
( $T: ty, $raw_data: expr, $length: expr ) => {{
|
||||
let t_size = size_of::<$T>();
|
||||
let mut arr: Vec<$T> = Vec::with_capacity($length);
|
||||
for i in 0..$length {
|
||||
arr.push(<$T>::from_ne_bytes(
|
||||
$raw_data[(i * t_size)..(i * t_size + t_size)]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
))
|
||||
}
|
||||
arr
|
||||
}};
|
||||
}
|
||||
|
||||
fn read_i32_array(raw_data: &Vec<u8>, length: usize) -> Vec<i32> {
|
||||
read_array!(i32, raw_data, length)
|
||||
}
|
||||
|
||||
fn read_i64_array(raw_data: &Vec<u8>, length: usize) -> Vec<i64> {
|
||||
read_array!(i64, raw_data, length)
|
||||
}
|
||||
|
||||
fn read_f64_array(raw_data: &Vec<u8>, length: usize) -> Vec<f64> {
|
||||
read_array!(f64, raw_data, length)
|
||||
}
|
||||
|
||||
fn read_bool_array(raw_data: &Vec<u8>) -> Vec<bool> {
|
||||
raw_data.iter().map(|b| *b == 1).collect()
|
||||
}
|
||||
|
||||
fn read_usize_array(raw_data: &Vec<u8>, length: usize) -> Vec<usize> {
|
||||
read_array!(usize, raw_data, length)
|
||||
}
|
||||
|
161
src/vm/mod.rs
161
src/vm/mod.rs
@ -1,49 +1,46 @@
|
||||
pub mod dm_type;
|
||||
pub mod dvm_value;
|
||||
mod mem;
|
||||
pub mod module;
|
||||
mod object_type;
|
||||
pub mod op_codes;
|
||||
pub mod platform;
|
||||
pub mod types;
|
||||
pub mod util;
|
||||
pub mod values;
|
||||
mod mem;
|
||||
|
||||
use crate::vm::mem::DmAllocObject;
|
||||
use crate::vm::dvm_value::DvmValue;
|
||||
use crate::vm::module::DmModule;
|
||||
use crate::vm::object_type::DmFn;
|
||||
use crate::vm::platform::init_platform_functions;
|
||||
use crate::vm::types::{DmFn, DmImplementation};
|
||||
use op_codes::*;
|
||||
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
||||
use std::collections::HashMap;
|
||||
use types::DmType;
|
||||
use util::{get_32_le, get_64_le};
|
||||
use values::DmValue;
|
||||
use values::DmValue::*;
|
||||
|
||||
pub type PlatformFunction = fn(args: Vec<DmValue>, &mut DmVirtualMachine) -> DmValue;
|
||||
pub type PlatformFunction = fn(args: Vec<DvmValue>, &mut DmVirtualMachine) -> DvmValue;
|
||||
|
||||
enum CallFrame {
|
||||
PlatformCall(PlatformCallFrame),
|
||||
DeimosCall(DeimosCallFrame)
|
||||
DeimosCall(DeimosCallFrame),
|
||||
}
|
||||
|
||||
pub struct PlatformCallFrame {
|
||||
pub name: String,
|
||||
pub args: Vec<DmValue>,
|
||||
pub args: Vec<DvmValue>,
|
||||
}
|
||||
|
||||
struct DeimosCallFrame {
|
||||
return_address: usize,
|
||||
}
|
||||
|
||||
pub struct DmVirtualMachine<'a> {
|
||||
modules: Vec<DmModule<'a>>,
|
||||
pub struct DmVirtualMachine {
|
||||
modules: Vec<DmModule>,
|
||||
platform_functions: HashMap<String, PlatformFunction>,
|
||||
ip: usize,
|
||||
call_stack: Vec<CallFrame>,
|
||||
registers: Vec<DmValue>,
|
||||
register_state_stack: Vec<Vec<DmValue>>,
|
||||
registers: Vec<DvmValue>,
|
||||
register_state_stack: Vec<Vec<DvmValue>>,
|
||||
}
|
||||
|
||||
impl DmVirtualMachine<'_> {
|
||||
impl DmVirtualMachine {
|
||||
pub fn new(modules: Vec<DmModule>) -> DmVirtualMachine {
|
||||
DmVirtualMachine {
|
||||
modules,
|
||||
@ -55,11 +52,11 @@ impl DmVirtualMachine<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call(
|
||||
&mut self,
|
||||
dm_function: &DmFn,
|
||||
args: Vec<DmValue>,
|
||||
) -> DmValue {
|
||||
pub fn call_by_fqn(&mut self, fn_fqn: &str, args: Vec<DvmValue>) -> DvmValue {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn call_fn(&mut self, dm_function: &DmFn, args: Vec<DvmValue>) -> DvmValue {
|
||||
// save current state
|
||||
self.call_stack.push(CallFrame::DeimosCall(DeimosCallFrame {
|
||||
return_address: self.ip,
|
||||
@ -68,7 +65,7 @@ impl DmVirtualMachine<'_> {
|
||||
|
||||
// zero registers and make sure there are enough for dm_function
|
||||
self.registers.clear();
|
||||
self.registers.resize(args.len(), DmValue::DmUnit);
|
||||
self.registers.resize(args.len(), DvmValue::Unit);
|
||||
|
||||
// push args
|
||||
for i in 0..args.len() {
|
||||
@ -76,7 +73,7 @@ impl DmVirtualMachine<'_> {
|
||||
}
|
||||
|
||||
// run the byte code
|
||||
self.run(&dm_function.byte_code);
|
||||
self.run_raw(&dm_function.byte_code);
|
||||
|
||||
// restore state
|
||||
self.registers = self.register_state_stack.pop().unwrap();
|
||||
@ -88,20 +85,22 @@ impl DmVirtualMachine<'_> {
|
||||
self.registers.get(0).unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn run(&mut self, code: &Vec<u8>) {
|
||||
pub fn run_raw(&mut self, code: &Vec<u8>) {
|
||||
let mut i = 0;
|
||||
while i < code.len() {
|
||||
match code[i] {
|
||||
MOV_INT => {
|
||||
let target_register = code[i + 1] as usize;
|
||||
let operand = get_32_le!(code, i, 2, u32);
|
||||
self.registers.insert(target_register, DmInt(operand as i32));
|
||||
self.registers
|
||||
.insert(target_register, DvmValue::Int(operand as i32));
|
||||
i += 6;
|
||||
}
|
||||
MOV_LONG => {
|
||||
let target_register = code[i + 1] as usize;
|
||||
let operand = get_64_le!(code, i, 2, u64);
|
||||
self.registers.insert(target_register, DmLong(operand as i64));
|
||||
self.registers
|
||||
.insert(target_register, DvmValue::Long(operand as i64));
|
||||
i += 10;
|
||||
}
|
||||
MOV_DOUBLE => { /* todo */ }
|
||||
@ -113,75 +112,13 @@ impl DmVirtualMachine<'_> {
|
||||
i += 3;
|
||||
}
|
||||
ALLOC => {
|
||||
i += 1;
|
||||
let target_register = code[i] as usize;
|
||||
i += 1;
|
||||
let symbol_name_length = get_32_le!(code, i, 0, usize);
|
||||
i += 4;
|
||||
let raw_symbol_name = code[i..(i + symbol_name_length)].to_vec();
|
||||
i += symbol_name_length;
|
||||
let symbol_name = String::from_utf8(raw_symbol_name).unwrap();
|
||||
|
||||
// find implementation
|
||||
let mut implementation_result: Option<&DmImplementation> = None;
|
||||
'module_find: for module in self.modules.iter() {
|
||||
if let Some(dm_implementation) = module.implementations.get(&symbol_name) {
|
||||
implementation_result = Some(dm_implementation);
|
||||
break 'module_find;
|
||||
}
|
||||
}
|
||||
if implementation_result == None {
|
||||
panic!("Implementation {} not found", symbol_name);
|
||||
}
|
||||
|
||||
let dm_implementation = implementation_result.unwrap();
|
||||
let size = dm_implementation.size_in_bytes;
|
||||
let layout = Layout::from_size_align(size, 4).unwrap();
|
||||
let pointer = unsafe { alloc_zeroed(layout) };
|
||||
let dm_object = Box::new(DmAllocObject {
|
||||
object_type: dm_implementation,
|
||||
data: pointer,
|
||||
size,
|
||||
layout,
|
||||
});
|
||||
let dm_object_pointer = Box::into_raw(dm_object);
|
||||
self.registers.insert(target_register, DmPointer(dm_object_pointer));
|
||||
i += 6;
|
||||
todo!()
|
||||
}
|
||||
DEALLOC => {
|
||||
let target_register = code[i + 1] as usize;
|
||||
let target_value = self.registers.get(target_register).unwrap();
|
||||
match target_value {
|
||||
DmPointer(ptr) => unsafe {
|
||||
let dm_object = Box::from_raw(ptr.clone());
|
||||
dealloc(dm_object.data, dm_object.layout);
|
||||
}
|
||||
_ => {
|
||||
panic!("Attempt to deallocate at the address stored in a register that is not a pointer.");
|
||||
}
|
||||
}
|
||||
self.registers.insert(target_register, DmUnit);
|
||||
i += 2;
|
||||
todo!()
|
||||
}
|
||||
MOV_INT_TO => {
|
||||
let target_register = code[i + 1] as usize;
|
||||
let target_value = self.registers.get(target_register).unwrap();
|
||||
if let DmPointer(dm_object_ptr) = target_value {
|
||||
let offset = get_32_le!(code, i, 2, isize);
|
||||
let new_address = unsafe {
|
||||
let dm_object = Box::from_raw(dm_object_ptr.clone());
|
||||
let data_ptr = dm_object.data;
|
||||
data_ptr.offset(offset).write(code[i + 6]);
|
||||
data_ptr.offset(offset + 1).write(code[i + 7]);
|
||||
data_ptr.offset(offset + 2).write(code[i + 8]);
|
||||
data_ptr.offset(offset + 3).write(code[i + 9]);
|
||||
Box::into_raw(dm_object)
|
||||
};
|
||||
self.registers.insert(target_register, DmPointer(new_address));
|
||||
i += 10;
|
||||
} else {
|
||||
panic!("target_register {} is not a Pointer", target_register);
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
PLATFORM_CALL => {
|
||||
i += 1;
|
||||
@ -222,13 +159,11 @@ impl DmVirtualMachine<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod dvm_run_tests {
|
||||
use super::*;
|
||||
use std::alloc::dealloc;
|
||||
|
||||
macro_rules! assert_register {
|
||||
( $expected: expr, $register: expr ) => {
|
||||
@ -241,8 +176,8 @@ mod dvm_run_tests {
|
||||
let mut code = Vec::new();
|
||||
add_mov_int(&mut code, 0, 1);
|
||||
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||
vm.run(&code);
|
||||
assert_register!(DmInt(1), vm.registers.get(0));
|
||||
vm.run_raw(&code);
|
||||
assert_register!(DvmValue::Int(1), vm.registers.get(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -250,8 +185,8 @@ mod dvm_run_tests {
|
||||
let mut code = Vec::new();
|
||||
add_mov_int(&mut code, 0, 0xffff);
|
||||
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||
vm.run(&code);
|
||||
assert_register!(DmInt(0xffff), vm.registers.get(0));
|
||||
vm.run_raw(&code);
|
||||
assert_register!(DvmValue::Int(0xffff), vm.registers.get(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -259,8 +194,8 @@ mod dvm_run_tests {
|
||||
let mut code = Vec::new();
|
||||
add_mov_int(&mut code, 0, 0x0fff_ffff);
|
||||
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||
vm.run(&code);
|
||||
assert_register!(DmInt(0x0fff_ffff), vm.registers.get(0));
|
||||
vm.run_raw(&code);
|
||||
assert_register!(DvmValue::Int(0x0fff_ffff), vm.registers.get(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -269,38 +204,34 @@ mod dvm_run_tests {
|
||||
add_mov_int(&mut code, 1, 1);
|
||||
add_mov_register(&mut code, 0, 1);
|
||||
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||
vm.registers.resize(2, DmUnit);
|
||||
vm.run(&code);
|
||||
assert_register!(DmInt(1), vm.registers.get(0));
|
||||
vm.registers.resize(2, DvmValue::Unit);
|
||||
vm.run_raw(&code);
|
||||
assert_register!(DvmValue::Int(1), vm.registers.get(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn mov_int_to_register_as_address() {
|
||||
let mut code = Vec::new();
|
||||
add_alloc(&mut code, 0, 4);
|
||||
add_mov_int_to(&mut code, 0, 0, 0xff);
|
||||
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||
vm.run(&code);
|
||||
let box_address = vm.registers.get(0).unwrap().clone();
|
||||
match box_address {
|
||||
DmPointer(ptr) => unsafe {
|
||||
let dm_object = Box::from_raw(ptr);
|
||||
assert_eq!(0xff, *dm_object.data);
|
||||
dealloc(dm_object.data, dm_object.layout);
|
||||
},
|
||||
vm.run_raw(&code);
|
||||
let actual = vm.registers.get(0).unwrap().clone();
|
||||
match actual {
|
||||
DvmValue::Pointer(value_box) => {
|
||||
assert_eq!(DvmValue::Int(0xff), *value_box);
|
||||
}
|
||||
_ => panic!("Target register is not a pointer"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn alloc_and_dealloc_expect_register_cleared() {
|
||||
let mut code = Vec::new();
|
||||
add_alloc(&mut code, 0, 4);
|
||||
add_dealloc(&mut code, 0);
|
||||
let mut vm = DmVirtualMachine::new(Vec::new());
|
||||
vm.run(&code);
|
||||
assert_register!(DmUnit, vm.registers.get(0));
|
||||
vm.run_raw(&code);
|
||||
assert_register!(DvmValue::Unit, vm.registers.get(0));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::get_32_le;
|
||||
use crate::vm::types::{DmFn, DmImplementation, DmInterface};
|
||||
use crate::vm::object_type::{DmFn, DmImplementation, DmInterface};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub const DEIMOS_MAGIC_NUMBER: u64 = 0x00_00_64_65_69_6d_6f_73; // ascii 'deimos'
|
||||
@ -7,13 +7,13 @@ pub const DEIMOS_MAGIC_STRING: [u8; 6] = [0x64, 0x65, 0x69, 0x6d, 0x6f, 0x73]; /
|
||||
|
||||
pub const COMPILER_VERSION_STRING: &str = "0.1.0";
|
||||
|
||||
pub struct DmModule<'a> {
|
||||
pub struct DmModule {
|
||||
pub compiler_version: String,
|
||||
pub fqn: String,
|
||||
pub short_name: String,
|
||||
pub constants: HashMap<String, DmConstant>,
|
||||
pub interfaces: HashMap<String, DmInterface<'a>>,
|
||||
pub implementations: HashMap<String, DmImplementation<'a>>,
|
||||
pub interfaces: HashMap<String, DmInterface>,
|
||||
pub implementations: HashMap<String, DmImplementation>,
|
||||
pub functions: HashMap<String, DmFn>,
|
||||
}
|
||||
|
||||
|
128
src/vm/object_type.rs
Normal file
128
src/vm/object_type.rs
Normal file
@ -0,0 +1,128 @@
|
||||
use crate::vm::dm_type::DmPrimitiveType;
|
||||
use crate::vm::mem::DmAllocObject;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DmObjectType {
|
||||
Interface(DmInterface),
|
||||
Implementation(DmImplementation),
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmFn {
|
||||
pub fqn: String,
|
||||
pub short_name: String,
|
||||
pub byte_code: Vec<u8>,
|
||||
pub num_registers: usize,
|
||||
}
|
||||
|
||||
impl PartialEq for DmFn {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.fqn == other.fqn
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmInterface {
|
||||
fqn: String,
|
||||
short_name: String,
|
||||
properties: HashMap<String, DmProperty>,
|
||||
virtual_methods: HashMap<String, DmVirtualMethod>,
|
||||
impl_methods: HashMap<String, DmFn>,
|
||||
}
|
||||
|
||||
impl PartialEq for DmInterface {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.fqn == other.fqn
|
||||
}
|
||||
}
|
||||
|
||||
impl DmInterface {
|
||||
fn get_fqn(&self) -> &str {
|
||||
&self.fqn
|
||||
}
|
||||
|
||||
fn get_method<'a>(&'a self, name: &str, self_object: &'a DmAllocObject) -> Option<&'a DmFn> {
|
||||
if self.impl_methods.contains_key(name) {
|
||||
self.impl_methods.get(name)
|
||||
} else if self.virtual_methods.contains_key(name) {
|
||||
self_object.implementation.get_method(name, self_object)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_property(&self, name: &str, self_object: &DmAllocObject) -> Option<&DmProperty> {
|
||||
self.properties.get(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmVirtualMethod {
|
||||
pub fqn: String,
|
||||
pub short_name: String,
|
||||
}
|
||||
|
||||
impl PartialEq for DmVirtualMethod {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.fqn == other.fqn
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmImplementation {
|
||||
pub fqn: String,
|
||||
pub short_name: String,
|
||||
pub interface: Rc<DmInterface>,
|
||||
pub properties: HashMap<String, DmProperty>,
|
||||
pub fields: HashMap<String, DmField>,
|
||||
pub size_in_bytes: usize,
|
||||
pub methods: HashMap<String, DmFn>,
|
||||
}
|
||||
|
||||
impl PartialEq for DmImplementation {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.fqn == other.fqn
|
||||
}
|
||||
}
|
||||
|
||||
impl DmImplementation {
|
||||
fn get_fqn(&self) -> &str {
|
||||
&self.fqn
|
||||
}
|
||||
|
||||
fn get_method<'a>(&'a self, name: &str, self_object: &'a DmAllocObject) -> Option<&'a DmFn> {
|
||||
self.methods.get(name)
|
||||
}
|
||||
|
||||
fn get_property(&self, name: &str, self_object: &DmAllocObject) -> Option<&DmProperty> {
|
||||
self.properties.get(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmProperty {
|
||||
pub name: String,
|
||||
pub data_offset: usize,
|
||||
pub primitive_type: Rc<DmPrimitiveType>,
|
||||
}
|
||||
|
||||
impl PartialEq for DmProperty {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name == other.name
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmField {
|
||||
name: String,
|
||||
primitive_type: Rc<DmPrimitiveType>,
|
||||
}
|
||||
|
||||
impl PartialEq for DmField {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name == other.name
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::vm::platform::std_lib::core::dm_print;
|
||||
use crate::vm::platform::std_lib::core::{dm_print, dm_println};
|
||||
use crate::vm::PlatformFunction;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@ -7,5 +7,6 @@ mod std_lib;
|
||||
pub fn init_platform_functions() -> HashMap<String, PlatformFunction> {
|
||||
let mut fns: HashMap<String, PlatformFunction> = HashMap::new();
|
||||
fns.insert(String::from("std::core::print"), dm_print);
|
||||
fns.insert(String::from("std::core::println"), dm_println);
|
||||
fns
|
||||
}
|
||||
|
@ -1,61 +1,36 @@
|
||||
use crate::vm::DmValue::*;
|
||||
use crate::vm::{mem, DmValue, DmVirtualMachine};
|
||||
use crate::vm::dvm_value::DvmValue;
|
||||
use crate::vm::DmVirtualMachine;
|
||||
|
||||
pub fn dm_print(args: Vec<DmValue>, vm: &mut DmVirtualMachine) -> DmValue {
|
||||
pub fn dm_print(args: Vec<DvmValue>, vm: &mut DmVirtualMachine) -> DvmValue {
|
||||
if args.len() != 1 {
|
||||
return DmUnit // TODO: make exception
|
||||
return DvmValue::Unit; // TODO: make exception
|
||||
}
|
||||
print!("{}", get_string(&args[0]));
|
||||
DvmValue::Unit
|
||||
}
|
||||
|
||||
pub fn dm_println(args: Vec<DvmValue>, vm: &mut DmVirtualMachine) -> DvmValue {
|
||||
if args.len() != 1 {
|
||||
return DvmValue::Unit;
|
||||
}
|
||||
println!("{}", get_string(&args[0]));
|
||||
DvmValue::Unit
|
||||
}
|
||||
|
||||
fn get_string(dvm_value: &DvmValue) -> String {
|
||||
match dvm_value {
|
||||
DvmValue::Byte(b) => b.to_string(),
|
||||
DvmValue::Int(i) => i.to_string(),
|
||||
DvmValue::Long(l) => l.to_string(),
|
||||
DvmValue::Double(d) => d.to_string(),
|
||||
DvmValue::Boolean(b) => b.to_string(),
|
||||
DvmValue::Pointer(value_box) => get_string(value_box),
|
||||
DvmValue::ByteArray(_) => todo!(),
|
||||
DvmValue::IntArray(_) => todo!(),
|
||||
DvmValue::LongArray(_) => todo!(),
|
||||
DvmValue::DoubleArray(_) => todo!(),
|
||||
DvmValue::BooleanArray(_) => todo!(),
|
||||
DvmValue::PointerArray(_) => todo!(),
|
||||
DvmValue::Unit => String::from("Unit"),
|
||||
}
|
||||
match &args[0] {
|
||||
DmByte(b) => {
|
||||
print!("{}", *b);
|
||||
}
|
||||
DmInt(i) => {
|
||||
print!("{}", *i);
|
||||
}
|
||||
DmLong(l) => {
|
||||
print!("{}", *l);
|
||||
}
|
||||
DmDouble(d) => {
|
||||
print!("{}", *d);
|
||||
}
|
||||
DmBoolean(b) => {
|
||||
print!("{}", *b);
|
||||
}
|
||||
DmPointer(ptr) => unsafe {
|
||||
let dm_alloc_object = Box::from_raw(*ptr);
|
||||
let dm_object_type = &dm_alloc_object.object_type;
|
||||
if let Some(to_string_method) = dm_object_type.get_method(String::from("std::core::Object::to_string"), &dm_alloc_object) {
|
||||
let call_result = vm.call(to_string_method, vec![args[0].clone()]);
|
||||
if let DmPointer(dm_string_pointer) = call_result {
|
||||
let dm_string_object = Box::from_raw(dm_string_pointer);
|
||||
let bytes_property = dm_string_object.object_type.get_property(String::from("bytes"), &dm_string_object).unwrap();
|
||||
let string_bytes_value = mem::get_property_value(bytes_property, &dm_string_object);
|
||||
if let DmByteArray(raw_string_bytes) = string_bytes_value {
|
||||
// TODO: other encodings
|
||||
print!("{}", String::from_utf8(raw_string_bytes).unwrap());
|
||||
} else {
|
||||
panic!("Expected std::core::String.bytes to be a ByteArray.")
|
||||
}
|
||||
} else {
|
||||
panic!("Expected {} to return a string.", to_string_method.fqn)
|
||||
}
|
||||
} else {
|
||||
println!("{}@{:?}", dm_object_type.get_fqn(), dm_alloc_object.data)
|
||||
}
|
||||
},
|
||||
DmByteArray(bs) => {
|
||||
|
||||
}
|
||||
DmIntArray(is) => {
|
||||
|
||||
}
|
||||
DmLongArray(ls) => {}
|
||||
DmDoubleArray(ds) => {}
|
||||
DmBooleanArray(bs) => {}
|
||||
DmPointerArray(ptrs) => {}
|
||||
DmUnit => {
|
||||
print!("Unit")
|
||||
},
|
||||
}
|
||||
DmUnit
|
||||
}
|
||||
|
162
src/vm/types.rs
162
src/vm/types.rs
@ -1,162 +0,0 @@
|
||||
use crate::vm::mem::DmAllocObject;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DmType<'a> {
|
||||
Byte,
|
||||
Int,
|
||||
Long,
|
||||
Double,
|
||||
Boolean,
|
||||
ObjectPointer(&'a dyn DmObjectType),
|
||||
ByteArray(usize),
|
||||
IntArray(usize),
|
||||
LongArray(usize),
|
||||
DoubleArray(usize),
|
||||
BooleanArray(usize),
|
||||
ObjectPointerArray(usize, &'a dyn DmObjectType),
|
||||
Unit,
|
||||
}
|
||||
|
||||
impl DmType<'_> {
|
||||
pub fn size_in_bytes(&self) -> usize {
|
||||
match self {
|
||||
DmType::Byte => 1,
|
||||
DmType::Int => 4,
|
||||
DmType::Long => 8,
|
||||
DmType::Double => 8,
|
||||
DmType::Boolean => 4,
|
||||
DmType::ObjectPointer(_) => 8,
|
||||
DmType::ByteArray(length) => *length,
|
||||
DmType::IntArray(length) => *length * 4,
|
||||
DmType::LongArray(length) => *length * 8,
|
||||
DmType::DoubleArray(length) => *length * 8,
|
||||
DmType::BooleanArray(length) => *length * 4,
|
||||
DmType::ObjectPointerArray(length, _) => length * 8,
|
||||
DmType::Unit => 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DmObjectType {
|
||||
fn get_fqn(&self) -> &String;
|
||||
fn get_method(&self, name: String, self_object: &DmAllocObject) -> Option<&DmFn>;
|
||||
fn get_property(&self, name: String, self_object: &DmAllocObject) -> Option<&DmProperty>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmFn {
|
||||
pub fqn: String,
|
||||
pub short_name: String,
|
||||
pub byte_code: Vec<u8>,
|
||||
pub num_registers: usize,
|
||||
}
|
||||
|
||||
impl PartialEq for DmFn {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.fqn == other.fqn
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmInterface<'a> {
|
||||
fqn: String,
|
||||
short_name: String,
|
||||
properties: HashMap<String, DmProperty<'a>>,
|
||||
virtual_methods: HashMap<String, DmVirtualMethod>,
|
||||
impl_methods: HashMap<String, DmFn>,
|
||||
}
|
||||
|
||||
impl PartialEq for DmInterface<'_> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.fqn == other.fqn
|
||||
}
|
||||
}
|
||||
|
||||
impl DmObjectType for DmInterface<'_> {
|
||||
fn get_fqn(&self) -> &String {
|
||||
&self.fqn
|
||||
}
|
||||
|
||||
fn get_method(&self, name: String, self_object: &DmAllocObject) -> Option<&DmFn> {
|
||||
if self.impl_methods.contains_key(&name) {
|
||||
self.impl_methods.get(&name)
|
||||
} else if self.virtual_methods.contains_key(&name) {
|
||||
self_object.object_type.get_method(name, &self_object)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_property(&self, name: String, self_object: &DmAllocObject) -> Option<&DmProperty> {
|
||||
self.properties.get(&name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmVirtualMethod {
|
||||
pub fqn: String,
|
||||
pub short_name: String,
|
||||
}
|
||||
|
||||
impl PartialEq for DmVirtualMethod {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.fqn == other.fqn
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmImplementation<'a> {
|
||||
pub fqn: String,
|
||||
pub short_name: String,
|
||||
pub interface: &'a DmInterface<'a>,
|
||||
pub properties: HashMap<String, DmProperty<'a>>,
|
||||
pub fields: HashMap<String, DmField<'a>>,
|
||||
pub size_in_bytes: usize,
|
||||
pub methods: HashMap<String, DmFn>
|
||||
}
|
||||
|
||||
impl PartialEq for DmImplementation<'_> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.fqn == other.fqn
|
||||
}
|
||||
}
|
||||
|
||||
impl DmObjectType for DmImplementation<'_> {
|
||||
fn get_fqn(&self) -> &String {
|
||||
&self.fqn
|
||||
}
|
||||
|
||||
fn get_method(&self, name: String, self_object: &DmAllocObject) -> Option<&DmFn> {
|
||||
self.methods.get(&name)
|
||||
}
|
||||
|
||||
fn get_property(&self, name: String, self_object: &DmAllocObject) -> Option<&DmProperty> {
|
||||
self.properties.get(&name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmProperty<'a> {
|
||||
pub name: String,
|
||||
pub data_offset: usize,
|
||||
pub dm_type: DmType<'a>
|
||||
}
|
||||
|
||||
impl PartialEq for DmProperty<'_> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name == other.name
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
pub struct DmField<'a> {
|
||||
name: String,
|
||||
dm_type: DmType<'a>,
|
||||
}
|
||||
|
||||
impl PartialEq for DmField<'_> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name == other.name
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
use crate::vm::mem::DmAllocObject;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum DmValue {
|
||||
DmByte(u8),
|
||||
DmInt(i32),
|
||||
DmLong(i64),
|
||||
DmDouble(f64),
|
||||
DmBoolean(bool),
|
||||
DmPointer(*mut DmAllocObject),
|
||||
DmByteArray(Vec<u8>),
|
||||
DmIntArray(Vec<i32>),
|
||||
DmLongArray(Vec<i64>),
|
||||
DmDoubleArray(Vec<f64>),
|
||||
DmBooleanArray(Vec<bool>),
|
||||
DmPointerArray(Vec<*mut DmAllocObject>),
|
||||
DmUnit,
|
||||
}
|
Loading…
Reference in New Issue
Block a user