163 lines
4.1 KiB
V
163 lines
4.1 KiB
V
module code
|
|
|
|
import freeflowuniverse.herolib.core.texttools
|
|
|
|
pub struct Function {
|
|
pub:
|
|
name string @[omitempty]
|
|
receiver Param @[omitempty]
|
|
is_pub bool @[omitempty]
|
|
mod string @[omitempty]
|
|
pub mut:
|
|
summary string @[omitempty]
|
|
description string @[omitempty]
|
|
params []Param @[omitempty]
|
|
body string @[omitempty]
|
|
result Param @[omitempty]
|
|
has_return bool @[omitempty]
|
|
}
|
|
|
|
// vgen_function generates a function statement for a function
|
|
pub fn (function Function) vgen(options WriteOptions) string {
|
|
mut params_ := function.params.clone()
|
|
optionals := function.params.filter(it.is_optional)
|
|
options_struct := Struct{
|
|
name: '${texttools.pascal_case(function.name)}Options'
|
|
attrs: [Attribute{
|
|
name: 'params'
|
|
}]
|
|
fields: optionals.map(StructField{
|
|
name: it.name
|
|
description: it.description
|
|
typ: it.typ
|
|
})
|
|
}
|
|
if optionals.len > 0 {
|
|
params_ << Param{
|
|
name: 'options'
|
|
typ: type_from_symbol(options_struct.name)
|
|
}
|
|
}
|
|
|
|
params := params_.filter(!it.is_optional).map(it.vgen()).join(', ')
|
|
|
|
receiver_ := Param{
|
|
...function.receiver
|
|
typ: if function.receiver.typ is Result {
|
|
function.receiver.typ.typ
|
|
} else {
|
|
function.receiver.typ
|
|
}
|
|
}
|
|
receiver := if receiver_.vgen().trim_space() != '' {
|
|
'(${receiver_.vgen()})'
|
|
} else {
|
|
''
|
|
}
|
|
|
|
name := texttools.name_fix(function.name)
|
|
result := function.result.typ.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 new_function(code string) !Function {
|
|
// TODO: implement function from file line
|
|
return parse_function(code)!
|
|
}
|
|
|
|
pub fn parse_function(code_ string) !Function {
|
|
// Extract comments and actual function code
|
|
mut lines := code_.split_into_lines()
|
|
mut comment_lines := []string{}
|
|
mut function_lines := []string{}
|
|
mut in_function := false
|
|
|
|
for line in lines {
|
|
trimmed := line.trim_space()
|
|
if !in_function && trimmed.starts_with('//') {
|
|
comment_lines << trimmed.trim_string_left('//').trim_space()
|
|
} else if !in_function && (trimmed.starts_with('pub fn') || trimmed.starts_with('fn')) {
|
|
in_function = true
|
|
function_lines << line
|
|
} else if in_function {
|
|
function_lines << line
|
|
}
|
|
}
|
|
|
|
// Process the function code
|
|
mut code := function_lines.join('\n').trim_space()
|
|
is_pub := code.starts_with('pub ')
|
|
if is_pub {
|
|
code = code.trim_string_left('pub ').trim_space()
|
|
}
|
|
|
|
is_fn := code.starts_with('fn ')
|
|
if !is_fn {
|
|
return error('invalid function format')
|
|
}
|
|
code = code.trim_string_left('fn ').trim_space()
|
|
|
|
receiver := if code.starts_with('(') {
|
|
param_str := code.all_after('(').all_before(')').trim_space()
|
|
code = code.all_after(')').trim_space()
|
|
parse_param(param_str)!
|
|
} else {
|
|
Param{}
|
|
}
|
|
|
|
name := code.all_before('(').trim_space()
|
|
code = code.trim_string_left(name).trim_space()
|
|
|
|
params_str := code.all_after('(').all_before(')')
|
|
params := if params_str.trim_space() != '' {
|
|
params_str_lst := params_str.split(',')
|
|
params_str_lst.map(parse_param(it)!)
|
|
} else {
|
|
[]Param{}
|
|
}
|
|
// Extract the result type, handling the ! for result types
|
|
mut result_type := code.all_after(')').all_before('{').replace(' ', '')
|
|
mut has_return := false
|
|
|
|
// Check if the result type contains !
|
|
if result_type.contains('!') {
|
|
has_return = true
|
|
result_type = result_type.replace('!', '')
|
|
}
|
|
|
|
result := new_param(
|
|
v: result_type
|
|
)!
|
|
|
|
body := if code.contains('{') { code.all_after('{').all_before_last('}') } else { '' }
|
|
|
|
// Process the comments into a description
|
|
description := comment_lines.join('\n')
|
|
|
|
return Function{
|
|
name: name
|
|
receiver: receiver
|
|
params: params
|
|
result: result
|
|
body: body
|
|
description: description
|
|
is_pub: is_pub
|
|
has_return: has_return
|
|
}
|
|
}
|