first version where we can actually compile hello world

Signed-off-by: Sarmonsiill <sarmonsiill@tilde.guru>
This commit is contained in:
Sarmonsiill 2022-11-01 15:35:19 +01:00
parent c6de1ed08c
commit 3bab1dbb4f
4 changed files with 214 additions and 23 deletions

View File

@ -1,3 +1,7 @@
__main,,
o'Hello World'
__greet;String|phrase,String|name;
o''#phrase #name'
..
__main;;
::greet;'Hello','david'..
..

2
run
View File

@ -1 +1 @@
clear && cat examples/hello_world.pte && PTE_DEBUG=true v run src/. examples/hello_world.pte -v
clear && cat examples/hello_world.pte && PTE_DEBUG=true $HOME/bin/v run src/. examples/hello_world.pte -v

202
src/core/core.v Normal file
View File

@ -0,0 +1,202 @@
module core
import os
import term
import rand
const debug = os.getenv('PTE_DEBUG')
pub struct Runtime {
pub mut:
args []string
target_file string
file_name string
mut:
cnt []string
objs []Object
found_main bool
transpiled_code string
}
struct Object {
name string
mut:
body []string
args []ArgObj
}
struct ArgObj {
name string
dft string /* default value of func param */
typ string
}
pub fn er(i string) {
println(term.bg_red(term.bright_white(i)))
}
pub fn dbg(i string) {
if debug == 'true' {
println(term.bright_blue(i))
}
}
pub fn (mut rn Runtime) run() {
rn.parse_file()
rn.parse_functions()
if !rn.found_main {
er('need to have a function called \'main\' declared')
exit(1)
}
mut t := []string{}
for obj in rn.objs {
t << transpile(obj)
}
rn.transpiled_code = 'module main'
rn.transpiled_code = '$rn.transpiled_code\n${t.join('')}'
dbg('End object: $rn')
rn.exec()
}
fn (rn Runtime) exec() {
file_name := 'tmp_${rand.uuid_v4()}.v'
os.write_file(file_name, rn.transpiled_code) or {
er('could not write transpiled file: $err')
exit(1)
}
result := os.execute('env v $file_name -o ./${rn.file_name}')
dbg('$result')
os.rm(file_name) or {
er('could not remove $file_name: $err')
exit(1)
}
}
fn (mut rn Runtime) parse_file() {
f := os.read_lines(rn.target_file) or {
er('could not read from ${rn.target_file}: $err')
exit(1)
}
rn.cnt = f
dbg('file content: ${f.join_lines()}')
}
fn (mut rn Runtime) parse_functions() {
mut inside_scope := false
mut last_index_flag := 0
mut continous_body := []string{}
for line in rn.cnt {
/* break scope and bump last_index_flag */
if line.starts_with('..') && inside_scope {
rn.objs[last_index_flag].body = continous_body
continous_body = []string{}
inside_scope = false
last_index_flag = rn.objs.len
dbg('last_index_flag is now set to $last_index_flag')
}
if inside_scope {
continous_body << line.trim_space()
}
if line.starts_with('__') {
inside_scope = true
// extract function name
x := line.all_after('__')
y := x.all_before(';')
dbg('FUNC: $y')
mut obj := Object{name: y}
if y == 'main' {
rn.found_main = true
}
// extract arguments
z := x.all_after_first(';')
c := z.all_before_last(';')
a := c.split(',')
dbg('args: $a')
if a.len > 0 {
for l in a {
s := l.split('|')
if s.len > 1 {
obj.args << ArgObj{
name: s[1]
typ: validate_type(s[0])
}
}
}
}
rn.objs << obj
}
}
}
fn validate_type(typ string) string {
mut ret := ''
match typ {
'String' { return 'string' }
'Int' { ret = 'i64' }
'Bool' { ret = 'bool' }
else {
er('"$typ" is not a type that Pytte recognizes')
exit(1)
}
}
return ret
}
fn transpile(obj Object) string {
mut s := []string{}
s << 'fn ${obj.name}('
if obj.args.len > 0 {
mut p := []string{}
for a in obj.args {
p << '${a.name} ${a.typ}'
}
s << p.join(',')
}
s << ') {'
if obj.body.len > 0 {
for b in obj.body {
s << lex(b)
}
}
s << '}'
dbg('code: ${s.join('')}')
return s.join('')
}
fn lex(row string) string {
mut s := ''
r := term.bright_yellow('TRANSPILING')
dbg('\t\t$r \t$row')
match true {
row.starts_with("o''") {
s = row.replace("o''", "println('")
s = s.replace("#", "\$")
s = '$s )'
return s
}
row.starts_with('::') {
s = row.trim_string_left('::')
s = s.replace(';', '(')
s = s.replace('..', ')')
return s
} else {
s = ''
}
}
return s
}

View File

@ -2,43 +2,28 @@ module main
import os
import os.cmdline
import term
import core
const lang_name = 'pytte'
const lang_vers = 'v0.0.1'
const lang_line = '$lang_name ($lang_vers)'
const debug = os.getenv('PTE_DEBUG')
struct Runtime {
mut:
args []string
target_file string
}
fn main() {
mut rn := Runtime{}
mut rn := core.Runtime{}
rn.args = cmdline.only_options(os.args[1..])
file_args := cmdline.only_non_options(os.args[1..])
if file_args.len != 1 {
er('$lang_line needs a single target file to run/compile')
core.er('$lang_line needs a single target file to run/compile')
exit(1)
}
rn.target_file = file_args[0]
rn.file_name = file_args[0].all_after_last('/').all_before_last('.')
dbg('Runtime current state: $rn')
rn.run()
}
fn er(i string) {
println(term.bg_red(term.bright_white(i)))
}
fn dbg(i string) {
if debug == 'true' {
println(term.bg_cyan(term.bright_black(i)))
}
}