refactor: Change hero action syntax to verb.noun

- Change action name format from `obj.verb` to `verb.obj`
- Update decoder to look for `define.obj` or `configure.obj`
- Modify encoder export to use the new `define.obj` prefix
- Update all test constants and scripts to the new syntax
- Make Remark struct public for test visibility
This commit is contained in:
Mahmoud-Emad
2025-08-05 19:02:26 +03:00
parent 65d75a8148
commit b15c4cd15a
8 changed files with 187 additions and 178 deletions

View File

@@ -20,11 +20,11 @@ fn decode_struct[T](_ T, data string) !T {
// println(data)
$if T is $struct {
obj_name := texttools.snake_case(T.name.all_after_last('.'))
mut action_name := '${obj_name}.define'
mut action_name := 'define.${obj_name}'
if !data.contains(action_name) {
action_name = '${obj_name}.configure'
action_name = 'configure.${obj_name}'
if !data.contains(action_name) {
return error('Data does not contain action name: ${obj_name}.define or ${action_name}')
return error('Data does not contain action name: define.${obj_name} or ${action_name}')
}
}
actions_split := data.split('!!')

View File

@@ -40,10 +40,14 @@ struct ComplexStruct {
child ChildStruct
}
const blank_complex = '!!define.complex_struct'
const partial_complex = '!!define.complex_struct id: 42 name: testcomplex'
const blank_complex = '!!define.complex_struct
!!define.child_struct'
const partial_complex = '!!define.complex_struct id: 42 name: testcomplex
!!define.child_struct'
const full_complex = '!!define.complex_struct id: 42 name: testobject
!!define.complex_struct.child text: child_text number: 24
!!define.child_struct text: child_text number: 24
'
fn test_decode_complex() ! {
@@ -128,14 +132,14 @@ const person = Person{
}
fn test_decode() ! {
mut object := decode[Person]('')!
assert object == Person{}
object = decode[Person](person_heroscript)!
// Test decoding with proper person data
object := decode[Person](person_heroscript)!
assert object == person
// object = decode[ComplexStruct](full_complex) or {
// assert true
// ComplexStruct{}
// }
// Test that empty string fails as expected
decode[Person]('') or {
assert true // This should fail, which is correct
return
}
assert false // Should not reach here
}

View File

@@ -39,7 +39,7 @@ pub fn encode[T](val T) !string {
// export exports an encoder into encoded heroscript
pub fn (e Encoder) export() !string {
mut script := e.params.export(
pre: '!!${e.action_names.join('.')}.configure'
pre: '!!define.${e.action_names.join('.')}'
indent: ' '
skip_empty: true
)

View File

@@ -12,7 +12,7 @@ struct MyStruct {
}
// is the one we should skip
struct Remark {
pub struct Remark {
id int
}

View File

@@ -10,7 +10,7 @@ struct Base {
remarks []Remark
}
struct Remark {
pub struct Remark {
text string
}
@@ -75,8 +75,7 @@ struct Profile {
url string
}
const person_heroscript = "
!!define.person id:1 name:Bob birthday:'2012-12-12 00:00:00'
const person_heroscript = "!!define.person id:1 name:Bob age:21 birthday:'2012-12-12 00:00:00'
!!define.person.car name:'Bob\\'s car' year:2014
!!define.person.car.insurance provider:insurer
@@ -107,15 +106,14 @@ const person = Person{
]
}
const company_script = "
!!define.company name:'Tech Corp' founded:'2022-12-05 20:14'
!!define.company.person id:1 name:Bob birthday:'2012-12-12 00:00:00'
const company_script = "!!define.company name:'Tech Corp' founded:'2022-12-05 20:14'
!!define.company.person id:1 name:Bob age:21 birthday:'2012-12-12 00:00:00'
!!define.company.person.car name:'Bob\\'s car' year:2014
!!define.company.person.car.insurance provider:insurer
!!define.company.person.profile platform:Github url:github.com/example
!!define.company.person id:2 name:Alice birthday:'1990-06-20 00:00:00'
!!define.company.person id:2 name:Alice age:30 birthday:'1990-06-20 00:00:00'
!!define.company.person.car name:'Alice\\'s car' year:2018
!!define.company.person.car.insurance

View File

@@ -1,6 +1,5 @@
module encoderhero
pub struct PostgresqlClient {
pub mut:
name string = 'default'
@@ -11,14 +10,13 @@ pub mut:
dbname string = 'postgres'
}
const postgres_client_blank = '!!define.postgresql_client'
const postgres_client_full = '!!define.postgresql_client name:production user:app_user port:5433 host:db.example.com password:secret123 dbname:myapp'
const postgres_client_partial = '!!define.postgresql_client name:dev host:localhost password:devpass'
const postgres_client_blank = '!!postgresql_client.configure'
const postgres_client_full = '!!postgresql_client.configure name:production user:app_user port:5433 host:db.example.com password:secret123 dbname:myapp'
const postgres_client_partial = '!!postgresql_client.configure name:dev host:localhost password:devpass'
const postgres_client_complex = "
!!postgresql_client.configure name:staging user:stage_user port:5434 host:staging.db.com password:stagepass dbname:stagingdb
"
const postgres_client_complex = '
!!define.postgresql_client name:staging user:stage_user port:5434 host:staging.db.com password:stagepass dbname:stagingdb
'
fn test_postgres_client_decode_blank() ! {
mut client := decode[PostgresqlClient](postgres_client_blank)!
@@ -117,7 +115,7 @@ fn test_postgres_client_encode() ! {
host: '127.0.0.1'
password: 'devpassword'
dbname: 'devdb'
}
},
]
for client in test_cases {
@@ -134,22 +132,22 @@ fn test_postgres_client_encode() ! {
}
// Play script for interactive testing
const play_script = "
const play_script = '
# PostgresqlClient Encode/Decode Play Script
# This script demonstrates encoding and decoding PostgresqlClient configurations
!!postgresql_client.configure name:playground user:play_user
!!define.postgresql_client name:playground user:play_user
port:5432
host:localhost
password:playpass
dbname:playdb
# You can also use partial configurations
!!postgresql_client.configure name:quick_test host:127.0.0.1
!!define.postgresql_client name:quick_test host:127.0.0.1
# Default configuration (all defaults)
!!postgresql_client.configure
"
!!define.postgresql_client
'
fn test_play_script() ! {
// Test the play script with multiple configurations
@@ -160,7 +158,7 @@ fn test_play_script() ! {
mut clients := []PostgresqlClient{}
for line in lines {
if line.starts_with('!!postgresql_client.configure') {
if line.starts_with('!!define.postgresql_client') {
client := decode[PostgresqlClient](line)!
clients << client
}

View File

@@ -107,6 +107,16 @@ pub fn encode[T](t T, args EncodeArgs) !Params {
// struct_attrs := attrs_get_reflection(mytype)
$for field in T.fields {
// Check if field has skip attribute
mut should_skip := false
for attr in field.attrs {
if attr.contains('skip') {
should_skip = true
break
}
}
if !should_skip {
val := t.$(field.name)
field_attrs := attrs_get(field.attrs)
mut key := field.name
@@ -202,6 +212,7 @@ pub fn encode[T](t T, args EncodeArgs) !Params {
} $else {
}
}
}
return params
}

View File

@@ -202,8 +202,6 @@ generate_test.v
dbfs_test.v
namedb_test.v
timetools_test.v
encoderhero/encoder_test.v
encoderhero/decoder_test.v
code/codeparser
gittools_test.v
link_def_test.v