Compare commits
	
		
			2 Commits
		
	
	
		
			bb2edc1d49
			...
			cccbc6d819
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | cccbc6d819 | ||
|   | d99ccf8807 | 
							
								
								
									
										398
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										398
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -2,6 +2,404 @@ | |||||||
| # It is not intended for manual editing. | # It is not intended for manual editing. | ||||||
| version = 4 | 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]] | [[package]] | ||||||
| name = "deimos" | name = "deimos" | ||||||
| version = "0.1.0" | 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" | path = "src/bin/dvm/main.rs" | ||||||
| 
 | 
 | ||||||
| [dependencies] | [dependencies] | ||||||
|  | pest = "2.7.14" | ||||||
|  | clap = { version = "4.5.23", features = ["derive"] } | ||||||
|  | pest_derive = "2.7.14" | ||||||
|  | |||||||
| @ -1,6 +1,5 @@ | |||||||
| ns std::collections | ns std::collections | ||||||
| 
 | 
 | ||||||
| pub int Collection<T : PartialEq> : Monad { | pub int Collection<T> : Monad { | ||||||
|     size: Int |     size: Int | ||||||
|     fn contains(element: T): Bool |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,82 +2,54 @@ ns std::collections | |||||||
| 
 | 
 | ||||||
| use std::collections::Collection | use std::collections::Collection | ||||||
| 
 | 
 | ||||||
| pub int List<T : PartialEq> : Collection<T> { | pub int Stack<T> : Collection<T> { | ||||||
|     fn add(element: T) |     fn push(element: T) | ||||||
|     fn remove(element: T) |     fn pop(): Option<T> | ||||||
| 
 |  | ||||||
|     fn index_of(element: T): Option<Int> |  | ||||||
|     fn get_at(index: Int): Option<T> |     fn get_at(index: Int): Option<T> | ||||||
|     fn remove_at(index: Int): Option<T> |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // This implies that Int, Long, and Double don't implement Zero, because 0 could reasonably mean something | pub impl ArrayStack<T : Default | Empty> : Stack<T> { | ||||||
| // whereas Unit means "null" for objects |     fld arr: mut Array<T> = array::of_length(16, std::reflect::default_or_empty<T>) | ||||||
| pub impl ArrayList<T : PartialEq> : List<T> { |     fld current_index: mut Int = 0 | ||||||
| 
 | 
 | ||||||
|     mut fld arr: Array<T> |     impl fn <U> map(m) { | ||||||
|     mut fld current_index: Int = 0 |         let result: mut Array<U> = array::of_length(arr.length, std::reflect::default_or_empty<U>) | ||||||
|     fld zero: Zero<T> |         for (element, i) in arr.iter_with_indices() { | ||||||
| 
 |             result[i] = m(element) | ||||||
|     pub ctor(items: Array<T>, zero: Zero<T>) { |         } | ||||||
|         arr = items |         result | ||||||
|         self.zero = zero |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub ctor(size: Int, zero: Zero<T>) { |     impl fn <U> flat_map(m) { | ||||||
|         arr = array::with_size(size, zero) |         let result: mut Array<U> = array::of_length(arr.length, std::reflect::default_or_empty<Array<U>>) | ||||||
|         self.zero = zero |         for (element, i) in arr.iter_with_indices() { | ||||||
|  |             result[i] = m(element) | ||||||
|  |         } | ||||||
|  |         array::flatten(result) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub ctor(zero: Zero<T>) { |     impl fn get_size() = current_index | ||||||
|         arr = array::with_size(8, zero) |  | ||||||
|         self.zero = zero |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     impl fn add(element) { |     impl fn push(element) { | ||||||
|         if current_index == arr.length { |         if current_index == arr.length { | ||||||
|             arr = array::clone_with_size(arr.length * 2, zero) |             arr = array::clone(size = arr.length * 2, source = arr) | ||||||
|         } |         } | ||||||
|         arr[current_index] = element |         arr[current_index] = element | ||||||
|         current_index++ |         current_index++ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     impl fn remove(element) { |     impl fn pop() { | ||||||
|         let index = index_of(element).get_or_throw(() => NoSuchElementException()) |         if current_index > 0 { | ||||||
|         arr[index] = T::default |             let element = arr[current_index - 1] | ||||||
|     } |             current_index-- | ||||||
| 
 |             return Some(element) | ||||||
|     impl fn index_of(element) { |  | ||||||
|         for (e, index) in arr.iter_with_index() { |  | ||||||
|             if e == element { |  | ||||||
|                 return Some(index) |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|         None |         None | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     impl fn get_at(index) { |     impl fn get_at(index) = index < arr.length ? Some(arr[index]) : None | ||||||
|         if index >= arr.length || index < 0 { |  | ||||||
|             return None |  | ||||||
|         } |  | ||||||
|         let item = arr[index] |  | ||||||
|         item == zero ? None : Some(item) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     impl fn remove_at(index) { |  | ||||||
|         if index <= arr.length || index < 0 { |  | ||||||
|             return None |  | ||||||
|         } |  | ||||||
|         let element = arr[index] |  | ||||||
|         if element == zero { |  | ||||||
|             return None |  | ||||||
|         } |  | ||||||
|         arr[index] = zero.item |  | ||||||
|         Some(element) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub mod list { | pub mod stack { | ||||||
|     pub fn of<T : PartialEq>(items: ...T): List<T> = ArrayList(items) |     pub fn of<T : PartialEq>(items: ...T): List<T> = ArrayList(items) | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,9 @@ | |||||||
| ns std::core | ns std::core | ||||||
| 
 | 
 | ||||||
| pub int Array<T> : Monad { | pub int Array<T> : Monad + Default + Empty { | ||||||
|  |     const default = array::empty<Self> | ||||||
|  |     const empty = array::empty<Self> | ||||||
|  | 
 | ||||||
|     length: Int |     length: Int | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -9,6 +12,24 @@ pub mod array { | |||||||
|     // Usage: |     // Usage: | ||||||
|     // let int_array = array::of(1, 2, 3) |     // let int_array = array::of(1, 2, 3) | ||||||
|     // assert_eq(3, int_array.length) |     // assert_eq(3, int_array.length) | ||||||
|     decl pub fn of<T>(ts: ...T): Array<T> |     pub extern fn of<T>(ts: ...T): Array<T> | ||||||
|  | 
 | ||||||
|  |     pub extern fn of_length<T>(length: Int, init_value: T): Array<T> | ||||||
|  | 
 | ||||||
|  |     pub extern fn empty<T>(): Array<T> | ||||||
|  | 
 | ||||||
|  |     pub fn flatten<T>(ats: Array<Array<T>>): Array<T> { | ||||||
|  |         let total_ts = ats.map { ts -> ts.length } | ||||||
|  |             .reduce { acc, current -> acc + current } | ||||||
|  |         let result: mut Array<T> = of_length(total_ts, std::reflect::default_or_empty<T>) | ||||||
|  |         let i: mut Int = 0 | ||||||
|  |         for a in ats { | ||||||
|  |             for element in a { | ||||||
|  |                 result[i] = element | ||||||
|  |                 i++ | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         result | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -8,6 +8,6 @@ pub int Character : Display { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub impl Utf8Character(bytes: Array<Byte>) { | pub impl Utf8Character(bytes: Array<Byte>) { | ||||||
|     impl fn get_encoding() = Encoding::Utf8 |     encoding = Encoding::Utf8 | ||||||
|     impl fn to_string() = string::from_utf8_bytes(bytes) |     impl fn to_string() = string::from_utf8_bytes(bytes) | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								dm_lib/std/core/cls.dm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								dm_lib/std/core/cls.dm
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | ns std::core | ||||||
|  | 
 | ||||||
|  | pub cls Any { | ||||||
|  |     fqn: String | ||||||
|  |     simple_name: String | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub cls Default { | ||||||
|  |     default: Self | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub cls Empty { | ||||||
|  |     empty: Self | ||||||
|  | } | ||||||
| @ -1,5 +1,7 @@ | |||||||
| ns std::core | ns std::core | ||||||
| 
 | 
 | ||||||
| decl pub fn print(message: Any) | extern fn _print(message: Any) | ||||||
|  | extern fn _println(message: Any) | ||||||
| 
 | 
 | ||||||
| decl pub fn println(message: Any) | pub fn print(message: Any) = _print(message) | ||||||
|  | pub fn println(message: Any) = _println(message) | ||||||
|  | |||||||
| @ -14,9 +14,11 @@ pub int String : Display { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Utf8String(bytes: Array<Byte>) : String { | impl Utf8String(bytes: Array<Byte>) : String { | ||||||
|     impl fn get_encoding() = Encoding::Utf8 |     encoding = Encoding::Utf8 | ||||||
|     impl fn get_length() = bytes.length |     length = bytes.length | ||||||
|     impl fn get_characters() = todo('parse the utf8 bytes and return an Array<Character>') |     characters = lazy { | ||||||
|  |         todo('parse the utf8 bytes and return an Array<Character>') | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub mod string { | pub mod string { | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								dm_lib/std/reflect/util.dm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								dm_lib/std/reflect/util.dm
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | ns std::reflect | ||||||
|  | 
 | ||||||
|  | pub fn <T> default_or_empty() { | ||||||
|  |     T is Default ? T::default : T is Empty | ||||||
|  |         ? T::empty : throw IllegalArgumentException("Type ${T::fqn} extends neither Default nor Empty.") | ||||||
|  | } | ||||||
| @ -1,11 +1,22 @@ | |||||||
| use deimos::vm::op_codes::{add_mov_int, add_platform_call_to}; | use deimos::vm::op_codes::{add_mov_int, add_platform_call_to}; | ||||||
| use deimos::vm::DmVirtualMachine; | use deimos::vm::DmVirtualMachine; | ||||||
|  | use deimos::vm::dvm_value::DvmValue; | ||||||
| 
 | 
 | ||||||
| fn main() { | 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(); |     let mut code: Vec<u8> = Vec::new(); | ||||||
|     add_mov_int(&mut code, 0, 42); |     add_mov_int(&mut code, 0, 0x2a); // 42
 | ||||||
|     add_platform_call_to(&mut code, &String::from("std::core::print"), 0, 1, &vec![0u8]); |     add_platform_call_to( | ||||||
|  |         &mut code, | ||||||
|  |         &String::from("std::core::println"), | ||||||
|  |         0, | ||||||
|  |         1, | ||||||
|  |         &vec![0u8], | ||||||
|  |     ); | ||||||
|     let mut vm = DmVirtualMachine::new(Vec::new()); |     let mut vm = DmVirtualMachine::new(Vec::new()); | ||||||
|     vm.run(&mut code); |     vm.run_raw(&mut code); | ||||||
|     println!() |     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::lexer::Token; | ||||||
| use crate::parser::types::AstNode; | 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> { | 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!() |     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, | ||||||
|  | } | ||||||
							
								
								
									
										145
									
								
								src/vm/mem.rs
									
									
									
									
									
								
							
							
						
						
									
										145
									
								
								src/vm/mem.rs
									
									
									
									
									
								
							| @ -1,78 +1,95 @@ | |||||||
| use crate::vm::types::{DmImplementation, DmProperty, DmType}; | use crate::vm::dm_type::DmPrimitiveType; | ||||||
| use crate::vm::values::DmValue; | use crate::vm::dvm_value::DvmValue; | ||||||
|  | use crate::vm::object_type::DmProperty; | ||||||
|  | use crate::vm::object_type::DmImplementation; | ||||||
| use std::alloc::Layout; | use std::alloc::Layout; | ||||||
|  | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| pub struct DmAllocObject<'a> { | pub struct DmAllocObject { | ||||||
|     pub data: *mut u8, |     pub data: *mut u8, | ||||||
|     pub size: usize, |     pub size: usize, | ||||||
|     pub layout: Layout, |     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 { | pub unsafe fn get_property_value( | ||||||
|     let mut data: Vec<u8> = Vec::with_capacity(dm_property.dm_type.size_in_bytes()); |     dm_property: &DmProperty, | ||||||
|     for i in dm_property.data_offset..(dm_property.data_offset + dm_property.dm_type.size_in_bytes()) { |     self_object: &DmAllocObject, | ||||||
|         data.push(dm_property_object.data.offset(i as isize).read()); | ) -> 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 { |     match dm_property.primitive_type.as_ref() { | ||||||
|         DmType::Byte => { |         DmPrimitiveType::Byte => DvmValue::Byte(raw_data[0]), | ||||||
|             DmValue::DmByte(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 => { |         DmPrimitiveType::ByteArray(_) => DvmValue::ByteArray(raw_data), | ||||||
|             DmValue::DmInt(i32::from_ne_bytes(data[0..4].try_into().unwrap())) |         DmPrimitiveType::IntArray(length) => DvmValue::IntArray(read_i32_array(&raw_data, *length)), | ||||||
|  |         DmPrimitiveType::LongArray(length) => { | ||||||
|  |             DvmValue::LongArray(read_i64_array(&raw_data, *length)) | ||||||
|         } |         } | ||||||
|         DmType::Long => { |         DmPrimitiveType::DoubleArray(length) => { | ||||||
|             DmValue::DmLong(i64::from_ne_bytes(data[0..8].try_into().unwrap())) |             DvmValue::DoubleArray(read_f64_array(&raw_data, *length)) | ||||||
|         } |         } | ||||||
|         DmType::Double => { |         DmPrimitiveType::BooleanArray(length) => { | ||||||
|             DmValue::DmDouble(f64::from_ne_bytes(data[0..8].try_into().unwrap())) |             DvmValue::BooleanArray(read_bool_array(&raw_data)) | ||||||
|         } |  | ||||||
|         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::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; | pub mod module; | ||||||
|  | mod object_type; | ||||||
| pub mod op_codes; | pub mod op_codes; | ||||||
| pub mod platform; | pub mod platform; | ||||||
| pub mod types; |  | ||||||
| pub mod util; | 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::module::DmModule; | ||||||
|  | use crate::vm::object_type::DmFn; | ||||||
| use crate::vm::platform::init_platform_functions; | use crate::vm::platform::init_platform_functions; | ||||||
| use crate::vm::types::{DmFn, DmImplementation}; |  | ||||||
| use op_codes::*; | use op_codes::*; | ||||||
| use std::alloc::{alloc_zeroed, dealloc, Layout}; |  | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| use types::DmType; |  | ||||||
| use util::{get_32_le, get_64_le}; | 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 { | enum CallFrame { | ||||||
|     PlatformCall(PlatformCallFrame), |     PlatformCall(PlatformCallFrame), | ||||||
|     DeimosCall(DeimosCallFrame) |     DeimosCall(DeimosCallFrame), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct PlatformCallFrame { | pub struct PlatformCallFrame { | ||||||
|     pub name: String, |     pub name: String, | ||||||
|     pub args: Vec<DmValue>, |     pub args: Vec<DvmValue>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct DeimosCallFrame { | struct DeimosCallFrame { | ||||||
|     return_address: usize, |     return_address: usize, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct DmVirtualMachine<'a> { | pub struct DmVirtualMachine { | ||||||
|     modules: Vec<DmModule<'a>>, |     modules: Vec<DmModule>, | ||||||
|     platform_functions: HashMap<String, PlatformFunction>, |     platform_functions: HashMap<String, PlatformFunction>, | ||||||
|     ip: usize, |     ip: usize, | ||||||
|     call_stack: Vec<CallFrame>, |     call_stack: Vec<CallFrame>, | ||||||
|     registers: Vec<DmValue>, |     registers: Vec<DvmValue>, | ||||||
|     register_state_stack: Vec<Vec<DmValue>>, |     register_state_stack: Vec<Vec<DvmValue>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl DmVirtualMachine<'_> { | impl DmVirtualMachine { | ||||||
|     pub fn new(modules: Vec<DmModule>) -> DmVirtualMachine { |     pub fn new(modules: Vec<DmModule>) -> DmVirtualMachine { | ||||||
|         DmVirtualMachine { |         DmVirtualMachine { | ||||||
|             modules, |             modules, | ||||||
| @ -55,11 +52,11 @@ impl DmVirtualMachine<'_> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn call( |     pub fn call_by_fqn(&mut self, fn_fqn: &str, args: Vec<DvmValue>) -> DvmValue { | ||||||
|         &mut self, |         todo!() | ||||||
|         dm_function: &DmFn, |     } | ||||||
|         args: Vec<DmValue>, | 
 | ||||||
|     ) -> DmValue { |     pub fn call_fn(&mut self, dm_function: &DmFn, args: Vec<DvmValue>) -> DvmValue { | ||||||
|         // save current state
 |         // save current state
 | ||||||
|         self.call_stack.push(CallFrame::DeimosCall(DeimosCallFrame { |         self.call_stack.push(CallFrame::DeimosCall(DeimosCallFrame { | ||||||
|             return_address: self.ip, |             return_address: self.ip, | ||||||
| @ -68,7 +65,7 @@ impl DmVirtualMachine<'_> { | |||||||
| 
 | 
 | ||||||
|         // zero registers and make sure there are enough for dm_function
 |         // zero registers and make sure there are enough for dm_function
 | ||||||
|         self.registers.clear(); |         self.registers.clear(); | ||||||
|         self.registers.resize(args.len(), DmValue::DmUnit); |         self.registers.resize(args.len(), DvmValue::Unit); | ||||||
| 
 | 
 | ||||||
|         // push args
 |         // push args
 | ||||||
|         for i in 0..args.len() { |         for i in 0..args.len() { | ||||||
| @ -76,7 +73,7 @@ impl DmVirtualMachine<'_> { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // run the byte code
 |         // run the byte code
 | ||||||
|         self.run(&dm_function.byte_code); |         self.run_raw(&dm_function.byte_code); | ||||||
| 
 | 
 | ||||||
|         // restore state
 |         // restore state
 | ||||||
|         self.registers = self.register_state_stack.pop().unwrap(); |         self.registers = self.register_state_stack.pop().unwrap(); | ||||||
| @ -88,20 +85,22 @@ impl DmVirtualMachine<'_> { | |||||||
|         self.registers.get(0).unwrap().clone() |         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; |         let mut i = 0; | ||||||
|         while i < code.len() { |         while i < code.len() { | ||||||
|             match code[i] { |             match code[i] { | ||||||
|                 MOV_INT => { |                 MOV_INT => { | ||||||
|                     let target_register = code[i + 1] as usize; |                     let target_register = code[i + 1] as usize; | ||||||
|                     let operand = get_32_le!(code, i, 2, u32); |                     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; |                     i += 6; | ||||||
|                 } |                 } | ||||||
|                 MOV_LONG => { |                 MOV_LONG => { | ||||||
|                     let target_register = code[i + 1] as usize; |                     let target_register = code[i + 1] as usize; | ||||||
|                     let operand = get_64_le!(code, i, 2, u64); |                     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; |                     i += 10; | ||||||
|                 } |                 } | ||||||
|                 MOV_DOUBLE => { /* todo */ } |                 MOV_DOUBLE => { /* todo */ } | ||||||
| @ -113,75 +112,13 @@ impl DmVirtualMachine<'_> { | |||||||
|                     i += 3; |                     i += 3; | ||||||
|                 } |                 } | ||||||
|                 ALLOC => { |                 ALLOC => { | ||||||
|                     i += 1; |                     todo!() | ||||||
|                     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; |  | ||||||
|                 } |                 } | ||||||
|                 DEALLOC => { |                 DEALLOC => { | ||||||
|                     let target_register = code[i + 1] as usize; |                     todo!() | ||||||
|                     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; |  | ||||||
|                 } |                 } | ||||||
|                 MOV_INT_TO => { |                 MOV_INT_TO => { | ||||||
|                     let target_register = code[i + 1] as usize; |                     todo!() | ||||||
|                     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); |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|                 PLATFORM_CALL => { |                 PLATFORM_CALL => { | ||||||
|                     i += 1; |                     i += 1; | ||||||
| @ -222,13 +159,11 @@ impl DmVirtualMachine<'_> { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod dvm_run_tests { | mod dvm_run_tests { | ||||||
|     use super::*; |     use super::*; | ||||||
|     use std::alloc::dealloc; |  | ||||||
| 
 | 
 | ||||||
|     macro_rules! assert_register { |     macro_rules! assert_register { | ||||||
|         ( $expected: expr, $register: expr ) => { |         ( $expected: expr, $register: expr ) => { | ||||||
| @ -241,8 +176,8 @@ mod dvm_run_tests { | |||||||
|         let mut code = Vec::new(); |         let mut code = Vec::new(); | ||||||
|         add_mov_int(&mut code, 0, 1); |         add_mov_int(&mut code, 0, 1); | ||||||
|         let mut vm = DmVirtualMachine::new(Vec::new()); |         let mut vm = DmVirtualMachine::new(Vec::new()); | ||||||
|         vm.run(&code); |         vm.run_raw(&code); | ||||||
|         assert_register!(DmInt(1), vm.registers.get(0)); |         assert_register!(DvmValue::Int(1), vm.registers.get(0)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
| @ -250,8 +185,8 @@ mod dvm_run_tests { | |||||||
|         let mut code = Vec::new(); |         let mut code = Vec::new(); | ||||||
|         add_mov_int(&mut code, 0, 0xffff); |         add_mov_int(&mut code, 0, 0xffff); | ||||||
|         let mut vm = DmVirtualMachine::new(Vec::new()); |         let mut vm = DmVirtualMachine::new(Vec::new()); | ||||||
|         vm.run(&code); |         vm.run_raw(&code); | ||||||
|         assert_register!(DmInt(0xffff), vm.registers.get(0)); |         assert_register!(DvmValue::Int(0xffff), vm.registers.get(0)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
| @ -259,8 +194,8 @@ mod dvm_run_tests { | |||||||
|         let mut code = Vec::new(); |         let mut code = Vec::new(); | ||||||
|         add_mov_int(&mut code, 0, 0x0fff_ffff); |         add_mov_int(&mut code, 0, 0x0fff_ffff); | ||||||
|         let mut vm = DmVirtualMachine::new(Vec::new()); |         let mut vm = DmVirtualMachine::new(Vec::new()); | ||||||
|         vm.run(&code); |         vm.run_raw(&code); | ||||||
|         assert_register!(DmInt(0x0fff_ffff), vm.registers.get(0)); |         assert_register!(DvmValue::Int(0x0fff_ffff), vm.registers.get(0)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
| @ -269,38 +204,34 @@ mod dvm_run_tests { | |||||||
|         add_mov_int(&mut code, 1, 1); |         add_mov_int(&mut code, 1, 1); | ||||||
|         add_mov_register(&mut code, 0, 1); |         add_mov_register(&mut code, 0, 1); | ||||||
|         let mut vm = DmVirtualMachine::new(Vec::new()); |         let mut vm = DmVirtualMachine::new(Vec::new()); | ||||||
|         vm.registers.resize(2, DmUnit); |         vm.registers.resize(2, DvmValue::Unit); | ||||||
|         vm.run(&code); |         vm.run_raw(&code); | ||||||
|         assert_register!(DmInt(1), vm.registers.get(0)); |         assert_register!(DvmValue::Int(1), vm.registers.get(0)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     #[ignore] |  | ||||||
|     fn mov_int_to_register_as_address() { |     fn mov_int_to_register_as_address() { | ||||||
|         let mut code = Vec::new(); |         let mut code = Vec::new(); | ||||||
|         add_alloc(&mut code, 0, 4); |         add_alloc(&mut code, 0, 4); | ||||||
|         add_mov_int_to(&mut code, 0, 0, 0xff); |         add_mov_int_to(&mut code, 0, 0, 0xff); | ||||||
|         let mut vm = DmVirtualMachine::new(Vec::new()); |         let mut vm = DmVirtualMachine::new(Vec::new()); | ||||||
|         vm.run(&code); |         vm.run_raw(&code); | ||||||
|         let box_address = vm.registers.get(0).unwrap().clone(); |         let actual = vm.registers.get(0).unwrap().clone(); | ||||||
|         match box_address { |         match actual { | ||||||
|             DmPointer(ptr) => unsafe { |             DvmValue::Pointer(value_box) => { | ||||||
|                 let dm_object = Box::from_raw(ptr); |                 assert_eq!(DvmValue::Int(0xff), *value_box); | ||||||
|                 assert_eq!(0xff, *dm_object.data); |             } | ||||||
|                 dealloc(dm_object.data, dm_object.layout); |  | ||||||
|             }, |  | ||||||
|             _ => panic!("Target register is not a pointer"), |             _ => panic!("Target register is not a pointer"), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     #[ignore] |  | ||||||
|     fn alloc_and_dealloc_expect_register_cleared() { |     fn alloc_and_dealloc_expect_register_cleared() { | ||||||
|         let mut code = Vec::new(); |         let mut code = Vec::new(); | ||||||
|         add_alloc(&mut code, 0, 4); |         add_alloc(&mut code, 0, 4); | ||||||
|         add_dealloc(&mut code, 0); |         add_dealloc(&mut code, 0); | ||||||
|         let mut vm = DmVirtualMachine::new(Vec::new()); |         let mut vm = DmVirtualMachine::new(Vec::new()); | ||||||
|         vm.run(&code); |         vm.run_raw(&code); | ||||||
|         assert_register!(DmUnit, vm.registers.get(0)); |         assert_register!(DvmValue::Unit, vm.registers.get(0)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| use crate::get_32_le; | use crate::get_32_le; | ||||||
| use crate::vm::types::{DmFn, DmImplementation, DmInterface}; | use crate::vm::object_type::{DmFn, DmImplementation, DmInterface}; | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| 
 | 
 | ||||||
| pub const DEIMOS_MAGIC_NUMBER: u64 = 0x00_00_64_65_69_6d_6f_73; // ascii 'deimos'
 | 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 const COMPILER_VERSION_STRING: &str = "0.1.0"; | ||||||
| 
 | 
 | ||||||
| pub struct DmModule<'a> { | pub struct DmModule { | ||||||
|     pub compiler_version: String, |     pub compiler_version: String, | ||||||
|     pub fqn: String, |     pub fqn: String, | ||||||
|     pub short_name: String, |     pub short_name: String, | ||||||
|     pub constants: HashMap<String, DmConstant>, |     pub constants: HashMap<String, DmConstant>, | ||||||
|     pub interfaces: HashMap<String, DmInterface<'a>>, |     pub interfaces: HashMap<String, DmInterface>, | ||||||
|     pub implementations: HashMap<String, DmImplementation<'a>>, |     pub implementations: HashMap<String, DmImplementation>, | ||||||
|     pub functions: HashMap<String, DmFn>, |     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 crate::vm::PlatformFunction; | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| 
 | 
 | ||||||
| @ -7,5 +7,6 @@ mod std_lib; | |||||||
| pub fn init_platform_functions() -> HashMap<String, PlatformFunction> { | pub fn init_platform_functions() -> HashMap<String, PlatformFunction> { | ||||||
|     let mut fns: HashMap<String, PlatformFunction> = HashMap::new(); |     let mut fns: HashMap<String, PlatformFunction> = HashMap::new(); | ||||||
|     fns.insert(String::from("std::core::print"), dm_print); |     fns.insert(String::from("std::core::print"), dm_print); | ||||||
|  |     fns.insert(String::from("std::core::println"), dm_println); | ||||||
|     fns |     fns | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,61 +1,36 @@ | |||||||
| use crate::vm::DmValue::*; | use crate::vm::dvm_value::DvmValue; | ||||||
| use crate::vm::{mem, DmValue, DmVirtualMachine}; | 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 { |     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