WIP: start the proto interpreter

This commit is contained in:
2025-09-01 11:09:49 -06:00
parent d36e1bfd86
commit 23e84c263d

View File

@ -0,0 +1,65 @@
package interpreter
import (
"fmt"
"masonry/lang"
"strings"
)
type ProtoInterpreter struct {
entities map[string]*lang.Entity
endpoints map[string]*lang.Endpoint
server *lang.Server
}
func NewProtoInterpreter() *ProtoInterpreter {
return &ProtoInterpreter{
entities: make(map[string]*lang.Entity),
endpoints: make(map[string]*lang.Endpoint),
}
}
func (pi *ProtoInterpreter) Interpret(ast lang.AST) error {
for _, def := range ast.Definitions {
if def.Server != nil {
pi.server = def.Server
} else if def.Entity != nil {
pi.entities[def.Entity.Name] = def.Entity
} else if def.Endpoint != nil {
key := fmt.Sprintf("%s_%s", def.Endpoint.Method, strings.ReplaceAll(def.Endpoint.Path, "/", "_"))
pi.endpoints[key] = def.Endpoint
}
}
// Validate references
for _, endpoint := range pi.endpoints {
if endpoint.Entity != nil {
if _, exists := pi.entities[*endpoint.Entity]; !exists {
return fmt.Errorf("undefined entity referenced in endpoint request: %s", *endpoint.Entity)
}
}
if endpoint.Response != nil {
entity, exists := pi.entities[*endpoint.Entity]
if !exists {
return fmt.Errorf("undefined entity referenced in endpoint response: %s", *endpoint.Entity)
}
// validate the fields of the response
for _, field := range endpoint.Response.Fields {
// check for a field with the same name in the entity
found := false
for _, entityField := range entity.Fields {
if entityField.Name == field {
found = true
break
}
}
if !found {
return fmt.Errorf("undefined field referenced in endpoint response: %s", field)
}
}
}
}
return nil
}