Skip to content

Commit ed172cd

Browse files
committed
first commit
1 parent 5b8acf5 commit ed172cd

File tree

8 files changed

+341
-0
lines changed

8 files changed

+341
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
vvm
2+

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# VVM
2+
3+
Experimental Register-based Virtual Machine for V Programming Language

cjson.v

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
module main
2+
3+
import json
4+
5+
struct UseJson {
6+
x int
7+
}
8+
9+
fn suppress_json_warning() {
10+
json.encode(UseJson{})
11+
}
12+
13+
// struct C.cJSON {}
14+
fn C.cJSON_CreateObject() &C.cJSON
15+
16+
fn C.cJSON_CreateArray() &C.cJSON
17+
18+
// fn C.cJSON_CreateBool(bool) &C.cJSON
19+
fn C.cJSON_CreateTrue() &C.cJSON
20+
21+
fn C.cJSON_CreateFalse() &C.cJSON
22+
23+
fn C.cJSON_CreateNull() &C.cJSON
24+
25+
// fn C.cJSON_CreateNumber() &C.cJSON
26+
// fn C.cJSON_CreateString() &C.cJSON
27+
fn C.cJSON_CreateRaw(&u8) &C.cJSON
28+
29+
fn C.cJSON_IsInvalid(voidptr) bool
30+
31+
fn C.cJSON_IsFalse(voidptr) bool
32+
33+
// fn C.cJSON_IsTrue(voidptr) bool
34+
fn C.cJSON_IsBool(voidptr) bool
35+
36+
fn C.cJSON_IsNull(voidptr) bool
37+
38+
fn C.cJSON_IsNumber(voidptr) bool
39+
40+
fn C.cJSON_IsString(voidptr) bool
41+
42+
fn C.cJSON_IsArray(voidptr) bool
43+
44+
fn C.cJSON_IsObject(voidptr) bool
45+
46+
fn C.cJSON_IsRaw(voidptr) bool
47+
48+
fn C.cJSON_AddItemToObject(voidptr, &u8, voidptr)
49+
50+
fn C.cJSON_AddItemToArray(voidptr, voidptr)
51+
52+
fn C.cJSON_Delete(voidptr)
53+
54+
fn C.cJSON_Print(voidptr) &u8
55+
56+
@[inline]
57+
fn create_object() &C.cJSON {
58+
return C.cJSON_CreateObject()
59+
}
60+
61+
@[inline]
62+
fn create_array() &C.cJSON {
63+
return C.cJSON_CreateArray()
64+
}
65+
66+
@[inline]
67+
fn create_string(val string) &C.cJSON {
68+
return C.cJSON_CreateString(val.str)
69+
}
70+
71+
@[inline]
72+
fn create_number(val f64) &C.cJSON {
73+
return C.cJSON_CreateNumber(val)
74+
}
75+
76+
@[inline]
77+
fn create_bool(val bool) &C.cJSON {
78+
return C.cJSON_CreateBool(val)
79+
}
80+
81+
@[inline]
82+
fn create_true() &C.cJSON {
83+
return C.cJSON_CreateTrue()
84+
}
85+
86+
@[inline]
87+
fn create_false() &C.cJSON {
88+
return C.cJSON_CreateFalse()
89+
}
90+
91+
@[inline]
92+
fn create_null() &C.cJSON {
93+
return C.cJSON_CreateNull()
94+
}
95+
96+
@[inline]
97+
fn delete(b voidptr) {
98+
C.cJSON_Delete(b)
99+
}
100+
101+
@[inline]
102+
fn add_item_to_object(obj &C.cJSON, key string, item &C.cJSON) {
103+
C.cJSON_AddItemToObject(obj, key.str, item)
104+
}
105+
106+
@[inline]
107+
fn add_item_to_array(obj &C.cJSON, item &C.cJSON) {
108+
C.cJSON_AddItemToArray(obj, item)
109+
}
110+
111+
fn json_print(json_ &C.cJSON) string {
112+
s := C.cJSON_Print(json_)
113+
return unsafe { tos3(s) }
114+
}

ir/ir.v

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
module ir
2+
3+
import v.ast
4+
import v.pref
5+
import v.parser
6+
import strings
7+
8+
pub enum Ins {
9+
module_
10+
print_
11+
call_
12+
}
13+
14+
type Operand = int | string
15+
16+
@[minify]
17+
struct IR {
18+
pub:
19+
ins Ins
20+
op1 Operand
21+
op2 Operand
22+
res Operand
23+
}
24+
25+
@[heap]
26+
pub struct VVMIR {
27+
pub mut:
28+
ir_list []IR
29+
}
30+
31+
struct Tree {
32+
table &ast.Table = unsafe { nil }
33+
pref &pref.Preferences = unsafe { nil }
34+
mut:
35+
root Node // the root of tree
36+
}
37+
38+
// tree node
39+
pub type Node = C.cJSON
40+
41+
// create an object node
42+
@[inline]
43+
fn new_object() &Node {
44+
return C.cJSON_CreateObject()
45+
}
46+
47+
fn (mut i VVMIR) gen_module(mod &ast.Module) {
48+
}
49+
50+
fn (mut i VVMIR) gen_fn_decl(func &ast.FnDecl) {
51+
i.gen_stmts(func.stmts)
52+
}
53+
54+
fn (mut i VVMIR) gen_call(call &ast.CallExpr) {
55+
i.ir_list << IR{
56+
ins: .call_
57+
op1: call.name
58+
op2: (call.args[0].expr as ast.StringLiteral).val
59+
}
60+
}
61+
62+
fn (mut i VVMIR) gen_expr(expr &ast.Expr) {
63+
match expr {
64+
ast.CallExpr { i.gen_call(&expr) }
65+
else { dump(expr) }
66+
}
67+
}
68+
69+
fn (mut i VVMIR) gen_return(stmt &ast.Return) {
70+
for expr in stmt.exprs {
71+
i.gen_expr(&expr)
72+
}
73+
}
74+
75+
fn (mut i VVMIR) gen_stmt(stmt &ast.Stmt) {
76+
match stmt {
77+
ast.Module {
78+
i.gen_module(&stmt)
79+
}
80+
ast.FnDecl {
81+
i.gen_fn_decl(&stmt)
82+
}
83+
ast.Block {
84+
i.gen_stmts(stmt.stmts)
85+
}
86+
ast.Return {
87+
i.gen_return(&stmt)
88+
}
89+
ast.ExprStmt {
90+
i.gen_expr(&stmt.expr)
91+
}
92+
else {
93+
dump(stmt)
94+
}
95+
}
96+
}
97+
98+
fn (mut i VVMIR) gen_stmts(stmts []ast.Stmt) {
99+
for stmt in stmts {
100+
i.gen_stmt(&stmt)
101+
}
102+
}
103+
104+
fn (mut i VVMIR) gen_file(file &ast.File) {
105+
i.gen_stmts(file.stmts)
106+
}
107+
108+
pub fn (mut i VVMIR) parse_file(file string) {
109+
mut pref_ := &pref.Preferences{}
110+
pref_.fill_with_defaults()
111+
pref_.enable_globals = true
112+
//
113+
mut t := Tree{
114+
root: new_object()
115+
table: ast.new_table()
116+
pref: pref_
117+
}
118+
// parse file with comment
119+
ast_file := parser.parse_file(file, t.table, .parse_comments, t.pref)
120+
i.gen_file(ast_file)
121+
}
122+
123+
fn (op Operand) str() string {
124+
if op is string {
125+
return 's"${string(op)}"'
126+
} else {
127+
return 'unused'
128+
}
129+
}
130+
131+
fn (ii IR) str() string {
132+
return '${ii.ins:10s} | ${ii.op1:10s} | ${ii.op2:10s} | ${ii.res:10s}'
133+
}
134+
135+
pub fn (i VVMIR) str() string {
136+
eprintln('Collected IR:')
137+
mut s := strings.new_builder(100)
138+
for item in i.ir_list {
139+
s.write_string(item.str())
140+
}
141+
return s.str()
142+
}

main.v

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module main
2+
3+
import vm
4+
import ir
5+
import os
6+
import flag
7+
8+
struct VVMOptions {
9+
file string
10+
help bool
11+
debug bool
12+
dumpir bool
13+
args []string
14+
}
15+
16+
fn main() {
17+
mut fp := flag.new_flag_parser(os.args)
18+
fp.application('vvm')
19+
fp.version('0.0.1a')
20+
fp.description('This tool converts the V AST to an IR and executes on its own virtual machine')
21+
fp.skip_executable()
22+
23+
mut opts := &VVMOptions{
24+
debug: fp.bool('debug', `d`, false, 'show debug information')
25+
dumpir: fp.bool('dumpir', `D`, false, 'dump IR only')
26+
file: fp.string('file', `f`, '', 'Input file')
27+
help: fp.bool('help', `h`, false, 'show this help message')
28+
}
29+
30+
if opts.help {
31+
eprintln(fp.usage())
32+
} else if opts.file != '' {
33+
mut vvm_ir := ir.VVMIR{}
34+
vvm_ir.parse_file(opts.file)
35+
if opts.dumpir {
36+
eprintln(vvm_ir)
37+
} else {
38+
mut vvm_vm := vm.VVM{}
39+
eprintln(vvm_ir)
40+
vvm_vm.run(vvm_ir)
41+
}
42+
} else {
43+
eprintln(fp.usage())
44+
}
45+
}

samples/print.v

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
println('foobar')
3+
}

v.mod

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Module {
2+
name: 'vvm'
3+
description: ''
4+
version: ''
5+
license: ''
6+
dependencies: []
7+
}

vm/vm.v

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module vm
2+
3+
import ir
4+
5+
@[heap]
6+
pub struct VVM {
7+
}
8+
9+
pub fn (v &VVM) run(ir_ &ir.VVMIR) {
10+
eprintln('Running:')
11+
for i in ir_.ir_list {
12+
match i.ins {
13+
.call_ {
14+
fnc := i.op1 as string
15+
match fnc {
16+
'println' {
17+
println(i.op2 as string)
18+
}
19+
else {}
20+
}
21+
}
22+
else {}
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)