fix generated code compilation for example
This commit is contained in:
@@ -67,7 +67,7 @@ pub fn generate_method_handle(actor_name string, method ActorMethod) !Function {
|
||||
body += 'params_arr := json.raw_decode(action.params)!.arr()\n'
|
||||
for i, param in method.parameters {
|
||||
param_name := texttools.snake_case(param.name)
|
||||
decode_stmt := generate_decode_stmt('params_arr[${i}]', param)!
|
||||
decode_stmt := generate_decode_stmt('params_arr[${i}].str()', param)!
|
||||
body += '${param_name} := ${decode_stmt}'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ pub fn generate_client_method(method ActorMethod) !Function {
|
||||
name_fixed := texttools.snake_case(method.name)
|
||||
|
||||
call_params := if method.parameters.len > 0 {
|
||||
method.parameters.map(texttools.snake_case(it.name)).map('Any(${it})').join(', ')
|
||||
method.parameters.map(texttools.snake_case(it.name)).map('Any(${it}.str())').join(', ')
|
||||
} else {''}
|
||||
|
||||
params_stmt := if method.parameters.len == 0 {
|
||||
|
||||
@@ -2,7 +2,10 @@ module generator
|
||||
|
||||
import freeflowuniverse.herolib.core.code { Array, Folder, IFile, VFile, CodeItem, File, Function, Param, Import, Module, Struct, CustomCode, Result }
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.schemas.openrpc.codegen {content_descriptor_to_parameter}
|
||||
import freeflowuniverse.herolib.schemas.openrpc {ContentDescriptor}
|
||||
import freeflowuniverse.herolib.schemas.openrpc.codegen {content_descriptor_to_parameter, content_descriptor_to_struct}
|
||||
import freeflowuniverse.herolib.schemas.jsonschema {Schema}
|
||||
import freeflowuniverse.herolib.schemas.jsonschema.codegen as jsonschema_codegen {schema_to_struct}
|
||||
import freeflowuniverse.herolib.baobab.specification {ActorMethod, ActorSpecification}
|
||||
|
||||
const crud_prefixes = ['new', 'get', 'set', 'delete', 'list']
|
||||
@@ -14,24 +17,13 @@ pub fn generate_methods_file(spec ActorSpecification) !VFile {
|
||||
receiver := generate_methods_receiver(spec.name)
|
||||
receiver_param := Param {
|
||||
mutable: true
|
||||
name: name_snake
|
||||
name: name_snake[0].ascii_str() // receiver is first letter of domain
|
||||
typ: code.Result{code.Object{receiver.name}}
|
||||
}
|
||||
|
||||
mut items := [CodeItem(receiver), CodeItem(generate_core_factory(receiver_param))]
|
||||
for method in spec.methods {
|
||||
method_fn := generate_method_function(receiver_param, method)!
|
||||
// check if method is a Base Object CRUD Method and
|
||||
// if so generate the method's body
|
||||
body := match spec.method_type(method) {
|
||||
.base_object_new { base_object_new_body(method)! }
|
||||
.base_object_get { base_object_get_body(method)! }
|
||||
.base_object_set { base_object_set_body(method)! }
|
||||
.base_object_delete { base_object_delete_body(method)! }
|
||||
.base_object_list { base_object_list_body(method)! }
|
||||
else {"panic('implement')"}
|
||||
}
|
||||
items << Function{...method_fn, body: body}
|
||||
items << generate_method_code(receiver_param, ActorMethod{...method, category: spec.method_type(method)})!
|
||||
}
|
||||
|
||||
return VFile {
|
||||
@@ -52,14 +44,44 @@ fn generate_methods_receiver(name string) code.Struct {
|
||||
fn generate_core_factory(receiver code.Param) code.Function {
|
||||
return code.Function {
|
||||
is_pub: true
|
||||
name: 'new_${receiver.name}'
|
||||
name: 'new_${receiver.typ.symbol()}'
|
||||
body: "return ${receiver.typ.symbol().trim_left('!?')}{OSIS: osis.new()!}"
|
||||
result: receiver
|
||||
}
|
||||
}
|
||||
|
||||
// returns bodyless method prototype
|
||||
pub fn generate_method_function(receiver code.Param, method ActorMethod) !Function {
|
||||
pub fn generate_method_code(receiver code.Param, method ActorMethod) ![]CodeItem {
|
||||
result_param := content_descriptor_to_parameter(method.result)!
|
||||
|
||||
mut method_code := []CodeItem{}
|
||||
// TODO: document assumption
|
||||
obj_params := method.parameters.filter(if it.schema is Schema {it.schema.typ == 'object'} else {false}).map(content_descriptor_to_struct(it))
|
||||
if obj_param := obj_params[0] {
|
||||
method_code << obj_param
|
||||
}
|
||||
|
||||
// check if method is a Base Object CRUD Method and
|
||||
// if so generate the method's body
|
||||
body := match method.category {
|
||||
.base_object_new { base_object_new_body(method)! }
|
||||
.base_object_get { base_object_get_body(method)! }
|
||||
.base_object_set { base_object_set_body(method)! }
|
||||
.base_object_delete { base_object_delete_body(method)! }
|
||||
.base_object_list { base_object_list_body(method)! }
|
||||
else {"panic('implement')"}
|
||||
}
|
||||
|
||||
fn_prototype := generate_method_prototype(receiver, method)!
|
||||
method_code << Function{
|
||||
...fn_prototype
|
||||
body: body
|
||||
}
|
||||
return method_code
|
||||
}
|
||||
|
||||
// returns bodyless method prototype
|
||||
pub fn generate_method_prototype(receiver code.Param, method ActorMethod) !Function {
|
||||
result_param := content_descriptor_to_parameter(method.result)!
|
||||
return Function{
|
||||
name: texttools.snake_case(method.name)
|
||||
|
||||
@@ -3,6 +3,8 @@ module generator
|
||||
import freeflowuniverse.herolib.core.code { Array, Folder, IFile, VFile, CodeItem, File, Function, Param, Import, Module, Struct, CustomCode, Result }
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.schemas.openrpc {Example}
|
||||
import freeflowuniverse.herolib.schemas.jsonschema {Schema}
|
||||
import freeflowuniverse.herolib.schemas.jsonschema.codegen as jsonschema_codegen {schema_to_struct}
|
||||
import freeflowuniverse.herolib.schemas.openrpc.codegen {content_descriptor_to_parameter}
|
||||
import freeflowuniverse.herolib.baobab.specification {ActorMethod, ActorSpecification}
|
||||
|
||||
@@ -13,15 +15,12 @@ pub fn generate_methods_example_file(spec ActorSpecification) !VFile {
|
||||
receiver := generate_example_methods_receiver(spec.name)
|
||||
receiver_param := Param {
|
||||
mutable: true
|
||||
name: name_snake
|
||||
name: name_snake[0].ascii_str()
|
||||
typ: code.Result{code.Object{receiver.name}}
|
||||
}
|
||||
mut items := [CodeItem(receiver), CodeItem(generate_core_example_factory(receiver_param))]
|
||||
for method in spec.methods {
|
||||
method_fn := generate_method_function(receiver_param, method)!
|
||||
items << Function{...method_fn,
|
||||
body: generate_method_example_body(method_fn, method)!
|
||||
}
|
||||
items << generate_method_example_code(receiver_param, ActorMethod{...method, category: spec.method_type(method)})!
|
||||
}
|
||||
|
||||
return VFile {
|
||||
@@ -37,7 +36,7 @@ pub fn generate_methods_example_file(spec ActorSpecification) !VFile {
|
||||
fn generate_core_example_factory(receiver code.Param) code.Function {
|
||||
return code.Function {
|
||||
is_pub: true
|
||||
name: 'new_${receiver.name}_example'
|
||||
name: 'new_${texttools.snake_case(receiver.typ.symbol())}'
|
||||
body: "return ${receiver.typ.symbol().trim_left('!?')}{OSIS: osis.new()!}"
|
||||
result: receiver
|
||||
}
|
||||
@@ -51,15 +50,35 @@ fn generate_example_methods_receiver(name string) code.Struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_method_example_body(func Function, method ActorMethod) !string {
|
||||
return if !method_is_void(method)! {
|
||||
|
||||
// returns bodyless method prototype
|
||||
pub fn generate_method_example_code(receiver code.Param, method ActorMethod) ![]CodeItem {
|
||||
result_param := content_descriptor_to_parameter(method.result)!
|
||||
|
||||
mut method_code := []CodeItem{}
|
||||
// TODO: document assumption
|
||||
// obj_params := method.parameters.filter(if it.schema is Schema {it.schema.typ == 'object'} else {false}).map(schema_to_struct(it.schema as Schema))
|
||||
// if obj_param := obj_params[0] {
|
||||
// method_code << Struct{...obj_param, name: method.name}
|
||||
// }
|
||||
|
||||
// check if method is a Base Object CRUD Method and
|
||||
// if so generate the method's body
|
||||
body := if !method_is_void(method)! {
|
||||
if method.example.result is Example {
|
||||
"data := '${method.example.result.value}'
|
||||
return ${generate_decode_stmt('data', method.result)!}"
|
||||
"json_str := '${method.example.result.value}'
|
||||
return ${generate_decode_stmt('json_str', method.result)!}"
|
||||
} else {
|
||||
"return ${func.result.typ.empty_value()}"
|
||||
"return ${result_param.typ.empty_value()}"
|
||||
}
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
fn_prototype := generate_method_prototype(receiver, method)!
|
||||
method_code << Function{
|
||||
...fn_prototype
|
||||
body: body
|
||||
}
|
||||
return method_code
|
||||
}
|
||||
@@ -20,12 +20,12 @@ pub fn generate_methods_interface_declaration(spec ActorSpecification) !code.Int
|
||||
receiver := generate_methods_receiver(spec.name)
|
||||
receiver_param := Param {
|
||||
mutable: true
|
||||
name: name_snake
|
||||
name: name_snake[0].ascii_str()
|
||||
typ: code.Object{receiver.name}
|
||||
}
|
||||
return code.Interface {
|
||||
is_pub: true
|
||||
name: 'I${name_pascal}'
|
||||
methods: spec.methods.map(generate_method_function(receiver_param, it)!)
|
||||
methods: spec.methods.map(generate_method_prototype(receiver_param, it)!)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
module specification
|
||||
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core.code { Struct, Function }
|
||||
import freeflowuniverse.herolib.schemas.jsonschema { Schema, SchemaRef }
|
||||
import freeflowuniverse.herolib.schemas.openapi { Operation, Parameter, OpenAPI, Components, Info, PathItem, ServerSpec }
|
||||
import freeflowuniverse.herolib.schemas.openapi { Operation, Parameter, OpenAPI, Components, Info, PathItem, ServerSpec, MediaType }
|
||||
import freeflowuniverse.herolib.schemas.openrpc { ExamplePairing, Example, ExampleRef, ContentDescriptor, ErrorSpec }
|
||||
|
||||
// Helper function: Convert OpenAPI parameter to ContentDescriptor
|
||||
@@ -42,19 +43,36 @@ fn openapi_operation_to_actor_method(info openapi.OperationInfo) ActorMethod {
|
||||
}
|
||||
}
|
||||
|
||||
response_200 := info.operation.responses['200'].content['application/json']
|
||||
if schema_ := info.operation.payload_schema() {
|
||||
// TODO: document assumption
|
||||
schema := Schema{...schema_, title: texttools.pascal_case(info.operation.operation_id)}
|
||||
parameters << ContentDescriptor {name: 'data', schema: SchemaRef(schema)}
|
||||
}
|
||||
|
||||
mut success_responses := map[string]MediaType{}
|
||||
|
||||
for code, response in info.operation.responses {
|
||||
if code.starts_with('2') { // Matches all 2xx responses
|
||||
success_responses[code] = response.content['application/json']
|
||||
}
|
||||
}
|
||||
|
||||
if success_responses.len > 1 || success_responses.len == 0 {
|
||||
panic('Actor specification must specify one successful response.')
|
||||
}
|
||||
response_success := success_responses.values()[0]
|
||||
|
||||
mut result := ContentDescriptor{
|
||||
name: "result",
|
||||
description: "The response of the operation.",
|
||||
required: true,
|
||||
schema: response_200.schema
|
||||
schema: response_success.schema
|
||||
}
|
||||
|
||||
example_result := if response_200.example.str() != '' {
|
||||
example_result := if response_success.example.str() != '' {
|
||||
Example{
|
||||
name: 'Example response',
|
||||
value: response_200.example
|
||||
value: response_success.example
|
||||
}
|
||||
} else {Example{}}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ pub:
|
||||
parameters []ContentDescriptor
|
||||
result ContentDescriptor
|
||||
errors []ErrorSpec
|
||||
category MethodCategory
|
||||
}
|
||||
|
||||
pub struct BaseObject {
|
||||
|
||||
Reference in New Issue
Block a user