275 lines
6.0 KiB
V
275 lines
6.0 KiB
V
module codemodel
|
|
|
|
import os
|
|
import freeflowuniverse.herolib.core.texttools
|
|
import freeflowuniverse.herolib.core.pathlib
|
|
import freeflowuniverse.herolib.ui.console
|
|
|
|
pub struct WriteCode {
|
|
destination string
|
|
}
|
|
|
|
interface ICodeItem {
|
|
vgen() string
|
|
}
|
|
|
|
pub fn vgen(code []CodeItem) string {
|
|
mut str := ''
|
|
for item in code {
|
|
if item is Function {
|
|
str += '\n${item.vgen()}'
|
|
}
|
|
if item is Struct {
|
|
str += '\n${item.vgen()}'
|
|
}
|
|
if item is CustomCode {
|
|
str += '\n${item.vgen()}'
|
|
}
|
|
}
|
|
return str
|
|
}
|
|
|
|
// pub fn (code Code) vgen() string {
|
|
// return code.items.map(it.vgen()).join_lines()
|
|
// }
|
|
|
|
// vgen_import generates an import statement for a given type
|
|
pub fn (import_ Import) vgen() string {
|
|
types_str := if import_.types.len > 0 {
|
|
'{${import_.types.join(', ')}}'
|
|
} else {
|
|
''
|
|
} // comma separated string list of types
|
|
return 'import ${import_.mod} ${types_str}'
|
|
}
|
|
|
|
// TODO: enfore that cant be both mutable and shared
|
|
pub fn (type_ Type) vgen() string {
|
|
mut type_str := ''
|
|
if type_.is_mutable {
|
|
type_str += 'mut '
|
|
} else if type_.is_shared {
|
|
type_str += 'shared '
|
|
}
|
|
|
|
if type_.is_optional {
|
|
type_str += '?'
|
|
} else if type_.is_result {
|
|
type_str += '!'
|
|
}
|
|
|
|
return '${type_str} ${type_.symbol}'
|
|
}
|
|
|
|
pub fn (field StructField) vgen() string {
|
|
symbol := field.get_type_symbol()
|
|
mut vstr := '${field.name} ${symbol}'
|
|
if field.description != '' {
|
|
vstr += '// ${field.description}'
|
|
}
|
|
return vstr
|
|
}
|
|
|
|
pub fn (field StructField) get_type_symbol() string {
|
|
mut field_str := if field.structure.name != '' {
|
|
field.structure.get_type_symbol()
|
|
} else {
|
|
field.typ.symbol
|
|
}
|
|
|
|
if field.is_ref {
|
|
field_str = '&${field_str}'
|
|
}
|
|
|
|
return field_str
|
|
}
|
|
|
|
pub fn (structure Struct) get_type_symbol() string {
|
|
mut symbol := if structure.mod != '' {
|
|
'${structure.mod.all_after_last('.')}.${structure.name}'
|
|
} else {
|
|
structure.name
|
|
}
|
|
if structure.generics.len > 0 {
|
|
symbol = '${symbol}${vgen_generics(structure.generics)}'
|
|
}
|
|
|
|
return symbol
|
|
}
|
|
|
|
pub fn vgen_generics(generics map[string]string) string {
|
|
if generics.keys().len == 0 {
|
|
return ''
|
|
}
|
|
mut vstr := '['
|
|
for key, val in generics {
|
|
vstr += if val != '' { val } else { key }
|
|
}
|
|
return '${vstr}]'
|
|
}
|
|
|
|
// vgen_function generates a function statement for a function
|
|
pub fn (function Function) vgen(options WriteOptions) string {
|
|
mut params_ := function.params.map(Param{
|
|
...it
|
|
typ: Type{
|
|
symbol: if it.struct_.name != '' {
|
|
it.struct_.name
|
|
} else {
|
|
it.typ.symbol
|
|
}
|
|
}
|
|
})
|
|
|
|
optionals := params_.filter(it.is_optional)
|
|
options_struct := Struct{
|
|
name: '${texttools.name_fix_snake_to_pascal(function.name)}Options'
|
|
attrs: [Attribute{
|
|
name: 'params'
|
|
}]
|
|
fields: optionals.map(StructField{
|
|
name: it.name
|
|
description: it.description
|
|
typ: Type{
|
|
symbol: it.typ.symbol
|
|
}
|
|
})
|
|
}
|
|
if optionals.len > 0 {
|
|
params_ << Param{
|
|
name: 'options'
|
|
typ: Type{
|
|
symbol: options_struct.name
|
|
}
|
|
}
|
|
}
|
|
|
|
params := params_.filter(!it.is_optional).map('${it.name} ${it.typ.symbol}').join(', ')
|
|
|
|
receiver := function.receiver.vgen()
|
|
|
|
mut function_str := $tmpl('templates/function/function.v.template')
|
|
|
|
// if options.format {
|
|
// result := os.execute_opt('echo "${function_str.replace('$', '\\$')}" | v fmt') or {
|
|
// panic('${function_str}\n${err}')
|
|
// }
|
|
// function_str = result.output
|
|
// }
|
|
function_str = function_str.split_into_lines().filter(!it.starts_with('import ')).join('\n')
|
|
|
|
return if options_struct.fields.len != 0 {
|
|
'${options_struct.vgen()}\n${function_str}'
|
|
} else {
|
|
function_str
|
|
}
|
|
}
|
|
|
|
pub fn (param Param) vgen() string {
|
|
if param.name == '' {
|
|
return ''
|
|
}
|
|
sym := if param.struct_.name != '' {
|
|
param.struct_.get_type_symbol()
|
|
} else {
|
|
param.typ.symbol
|
|
}
|
|
|
|
mut vstr := '${param.name} ${sym}'
|
|
if param.typ.is_reference {
|
|
vstr = '&${vstr}'
|
|
}
|
|
if param.mutable {
|
|
vstr = 'mut ${vstr}'
|
|
}
|
|
return '(${vstr})'
|
|
}
|
|
|
|
// vgen_function generates a function statement for a function
|
|
pub fn (struct_ Struct) vgen() string {
|
|
gen := VGenerator{false}
|
|
return gen.generate_struct(struct_) or { panic(err) }
|
|
// mut struct_str := $tmpl('templates/struct/struct.v.template')
|
|
// return struct_str
|
|
// result := os.execute_opt('echo "${struct_str.replace('$', '\$')}" | v fmt') or {panic(err)}
|
|
// return result.output
|
|
}
|
|
|
|
pub struct VGenerator {
|
|
format bool
|
|
}
|
|
|
|
pub fn (gen VGenerator) generate_struct(struct_ Struct) !string {
|
|
name := if struct_.generics.len > 0 {
|
|
'${struct_.name}${vgen_generics(struct_.generics)}'
|
|
} else {
|
|
struct_.name
|
|
}
|
|
|
|
prefix := if struct_.is_pub {
|
|
'pub'
|
|
} else {
|
|
''
|
|
}
|
|
|
|
priv_fields := struct_.fields.filter(!it.is_mut && !it.is_pub).map(gen.generate_struct_field(it))
|
|
pub_fields := struct_.fields.filter(!it.is_mut && it.is_pub).map(gen.generate_struct_field(it))
|
|
mut_fields := struct_.fields.filter(it.is_mut && !it.is_pub).map(gen.generate_struct_field(it))
|
|
pub_mut_fields := struct_.fields.filter(it.is_mut && it.is_pub).map(gen.generate_struct_field(it))
|
|
|
|
mut struct_str := $tmpl('templates/struct/struct.v.template')
|
|
if gen.format {
|
|
result := os.execute_opt('echo "${struct_str.replace('$', '\$')}" | v fmt') or {
|
|
console.print_debug(struct_str)
|
|
panic(err)
|
|
}
|
|
return result.output
|
|
}
|
|
return struct_str
|
|
}
|
|
|
|
pub fn (gen VGenerator) generate_struct_field(field StructField) string {
|
|
symbol := field.get_type_symbol()
|
|
mut vstr := '${field.name} ${symbol}'
|
|
if field.description != '' {
|
|
vstr += '// ${field.description}'
|
|
}
|
|
return vstr
|
|
}
|
|
|
|
pub fn (custom CustomCode) vgen() string {
|
|
return custom.text
|
|
}
|
|
|
|
// vgen_function generates a function statement for a function
|
|
pub fn (result Result) vgen() string {
|
|
result_type := if result.structure.name != '' {
|
|
result.structure.get_type_symbol()
|
|
} else if result.typ.symbol == 'void' {
|
|
''
|
|
} else {
|
|
if result.typ.is_array {
|
|
'[]${result.typ.symbol}'
|
|
} else {
|
|
result.typ.symbol
|
|
}
|
|
}
|
|
str := if result.result {
|
|
'!'
|
|
} else if result.typ.is_result {
|
|
'!'
|
|
} else {
|
|
''
|
|
}
|
|
return '${str}${result_type}'
|
|
}
|
|
|
|
@[params]
|
|
pub struct WriteOptions {
|
|
pub:
|
|
format bool
|
|
overwrite bool
|
|
document bool
|
|
prefix string
|
|
}
|