Bind object initializers
This commit is contained in:
parent
a7ccc1b052
commit
d56f640d5f
16 changed files with 220 additions and 108 deletions
|
@ -104,7 +104,7 @@ const ObjectLiteralKind NodeKind = "ObjectLiteral"
|
|||
// ObjectLiteralProperty initializes a single object literal property.
|
||||
type ObjectLiteralProperty struct {
|
||||
NodeValue
|
||||
Name *Identifier `json:"name"` // the property to initialize.
|
||||
Property *ClassMemberToken `json:"property"` // the property to initialize.
|
||||
Value Expression `json:"value"` // the expression whose value to store into the property.
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,14 @@ type Token struct {
|
|||
|
||||
const TokenKind NodeKind = "Token"
|
||||
|
||||
// ClassMemberToken represents a real string class member token associated with its source location context.
|
||||
type ClassMemberToken struct {
|
||||
NodeValue
|
||||
Tok tokens.ClassMember `json:"tok"`
|
||||
}
|
||||
|
||||
const ClassMemberTokenKind NodeKind = "ClassMemberToken"
|
||||
|
||||
// ModuleToken represents a real string type token associated with its source location context.
|
||||
type ModuleToken struct {
|
||||
NodeValue
|
||||
|
|
|
@ -129,7 +129,7 @@ func Walk(v Visitor, node Node) {
|
|||
}
|
||||
}
|
||||
case *ObjectLiteralProperty:
|
||||
Walk(v, n.Name)
|
||||
Walk(v, n.Property)
|
||||
Walk(v, n.Value)
|
||||
case *LoadLocationExpression:
|
||||
if n.Object != nil {
|
||||
|
|
|
@ -187,7 +187,7 @@ func (b *binder) lookupSymbolToken(node ast.Node, tok tokens.Token, require bool
|
|||
if clmnm == "" {
|
||||
sym = member
|
||||
} else if class, isclass := member.(*symbols.Class); isclass {
|
||||
if clmember, has := class.Members[clmnm]; has {
|
||||
if clmember, has := class.Clmembers[clmnm]; has {
|
||||
// The member was found; validate that it's got the right accessibility.
|
||||
b.checkClassVisibility(node, class, clmember)
|
||||
sym = clmember
|
||||
|
@ -211,6 +211,7 @@ func (b *binder) lookupSymbolToken(node ast.Node, tok tokens.Token, require bool
|
|||
glog.V(5).Info("Failed to bind qualified token; %v: '%v'", extra, tok)
|
||||
if require {
|
||||
// If requested, issue an error.
|
||||
// TODO: edit distance checking to help suggest a fix.
|
||||
b.Diag().Errorf(errors.ErrorSymbolNotFound.At(node), tok, extra)
|
||||
}
|
||||
}
|
||||
|
@ -283,7 +284,7 @@ func (b *binder) requireFunctionType(node ast.Function) *symbols.FunctionType {
|
|||
|
||||
// registerFunctionType understands how to turn any function node into a type, and adds it to the type table. This
|
||||
// works for any kind of function-like AST node: module property, class property, or lambda.
|
||||
func (b *binder) registerFunctionType(node ast.Function) {
|
||||
func (b *binder) registerFunctionType(node ast.Function) *symbols.FunctionType {
|
||||
// Make a function type and inject it into the type table.
|
||||
var params []symbols.Type
|
||||
np := node.GetParameters()
|
||||
|
@ -316,6 +317,8 @@ func (b *binder) registerFunctionType(node ast.Function) {
|
|||
glog.V(7).Infof("Registered function type: '%v' => %v", node.GetName().Ident, tysym.Name())
|
||||
}
|
||||
b.types[node] = tysym
|
||||
|
||||
return tysym
|
||||
}
|
||||
|
||||
// requireVariableType fetches the non-nil registered type for a given variable.
|
||||
|
@ -325,7 +328,7 @@ func (b *binder) requireVariableType(node ast.Variable) symbols.Type {
|
|||
|
||||
// registerVariableType understands how to turn any variable node into a type, and adds it to the type table. This
|
||||
// works for any kind of variable-like AST node: module property, class property, parameter, or local variable.
|
||||
func (b *binder) registerVariableType(node ast.Variable) {
|
||||
func (b *binder) registerVariableType(node ast.Variable) symbols.Type {
|
||||
var tysym symbols.Type
|
||||
|
||||
// If there is an explicit node type, use it.
|
||||
|
@ -343,4 +346,6 @@ func (b *binder) registerVariableType(node ast.Variable) {
|
|||
glog.V(7).Infof("Registered variable type: '%v' => %v", node.GetName().Ident, tysym.Name())
|
||||
}
|
||||
b.types[node] = tysym
|
||||
|
||||
return tysym
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func (b *binder) bindClass(node *ast.Class, parent *symbols.Module) *symbols.Cla
|
|||
// Next, bind each member at the symbolic level; in particular, we do not yet bind bodies of methods.
|
||||
if node.Members != nil {
|
||||
for memtok, member := range *node.Members {
|
||||
class.Members[memtok] = b.bindClassMember(member, class)
|
||||
class.Clmembers[memtok] = b.bindClassMember(member, class)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,19 +61,19 @@ func (b *binder) bindClassProperty(node *ast.ClassProperty, parent *symbols.Clas
|
|||
glog.V(3).Infof("Binding class '%v' property '%v'", parent.Name(), node.Name.Ident)
|
||||
|
||||
// Look up this node's type and inject it into the type table.
|
||||
b.registerVariableType(node)
|
||||
return symbols.NewClassPropertySym(node, parent)
|
||||
ty := b.registerVariableType(node)
|
||||
return symbols.NewClassPropertySym(node, parent, ty)
|
||||
}
|
||||
|
||||
func (b *binder) bindClassMethod(node *ast.ClassMethod, parent *symbols.Class) *symbols.ClassMethod {
|
||||
glog.V(3).Infof("Binding class '%v' method '%v'", parent.Name(), node.Name.Ident)
|
||||
|
||||
// Make a function type out of this method and inject it into the type table.
|
||||
b.registerFunctionType(node)
|
||||
ty := b.registerFunctionType(node)
|
||||
|
||||
// Note that we don't actually bind the body of this method yet. Until we have gone ahead and injected *all*
|
||||
// top-level symbols into the type table, we would potentially encounter missing intra-module symbols.
|
||||
return symbols.NewClassMethodSym(node, parent)
|
||||
return symbols.NewClassMethodSym(node, parent, ty)
|
||||
}
|
||||
|
||||
func (b *binder) bindClassMethodBody(method *symbols.ClassMethod) {
|
||||
|
|
29
pkg/compiler/binder/func.go
Normal file
29
pkg/compiler/binder/func.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2016 Marapongo, Inc. All rights reserved.
|
||||
|
||||
package binder
|
||||
|
||||
import (
|
||||
"github.com/marapongo/mu/pkg/compiler/ast"
|
||||
"github.com/marapongo/mu/pkg/compiler/symbols"
|
||||
)
|
||||
|
||||
// bindFunctionBody binds a function body, including a scope, its parameters, and its expressions and statements.
|
||||
func (b *binder) bindFunctionBody(node ast.Function) {
|
||||
// Enter a new scope, bind the parameters, and then bind the body using a visitor.
|
||||
scope := b.scope.Push()
|
||||
defer scope.Pop()
|
||||
params := node.GetParameters()
|
||||
if params != nil {
|
||||
for _, param := range *params {
|
||||
// Register this variable's type and associate its name with the identifier.
|
||||
b.registerVariableType(param)
|
||||
b.scope.TryRegister(param, symbols.NewLocalVariableSym(param))
|
||||
}
|
||||
}
|
||||
|
||||
body := node.GetBody()
|
||||
if body != nil {
|
||||
v := newASTBinder(b, node)
|
||||
ast.Walk(v, body)
|
||||
}
|
||||
}
|
|
@ -74,19 +74,19 @@ func (b *binder) bindModuleProperty(node *ast.ModuleProperty, parent *symbols.Mo
|
|||
glog.V(3).Infof("Binding module '%v' property '%v'", parent.Name(), node.Name.Ident)
|
||||
|
||||
// Look up this node's type and inject it into the type table.
|
||||
b.registerVariableType(node)
|
||||
return symbols.NewModulePropertySym(node, parent)
|
||||
ty := b.registerVariableType(node)
|
||||
return symbols.NewModulePropertySym(node, parent, ty)
|
||||
}
|
||||
|
||||
func (b *binder) bindModuleMethod(node *ast.ModuleMethod, parent *symbols.Module) *symbols.ModuleMethod {
|
||||
glog.V(3).Infof("Binding module '%v' method '%v'", parent.Name(), node.Name.Ident)
|
||||
|
||||
// Make a function type out of this method and inject it into the type table.
|
||||
b.registerFunctionType(node)
|
||||
ty := b.registerFunctionType(node)
|
||||
|
||||
// Note that we don't actually bind the body of this method yet. Until we have gone ahead and injected *all*
|
||||
// top-level symbols into the type table, we would potentially encounter missing intra-module symbols.
|
||||
return symbols.NewModuleMethodSym(node, parent)
|
||||
return symbols.NewModuleMethodSym(node, parent, ty)
|
||||
}
|
||||
|
||||
func (b *binder) bindModuleBodies(module *symbols.Module) {
|
||||
|
@ -102,7 +102,7 @@ func (b *binder) bindModuleBodies(module *symbols.Module) {
|
|||
case *symbols.ModuleMethod:
|
||||
b.bindModuleMethodBody(m)
|
||||
case *symbols.Class:
|
||||
for _, cmember := range m.Members {
|
||||
for _, cmember := range m.Clmembers {
|
||||
switch cm := cmember.(type) {
|
||||
case *symbols.ClassMethod:
|
||||
b.bindClassMethodBody(cm)
|
||||
|
|
|
@ -11,27 +11,6 @@ import (
|
|||
"github.com/marapongo/mu/pkg/util/contract"
|
||||
)
|
||||
|
||||
// bindFunctionBody binds a function body, including a scope, its parameters, and its expressions and statements.
|
||||
func (b *binder) bindFunctionBody(node ast.Function) {
|
||||
// Enter a new scope, bind the parameters, and then bind the body using a visitor.
|
||||
scope := b.scope.Push()
|
||||
defer scope.Pop()
|
||||
params := node.GetParameters()
|
||||
if params != nil {
|
||||
for _, param := range *params {
|
||||
// Register this variable's type and associate its name with the identifier.
|
||||
b.registerVariableType(param)
|
||||
b.scope.TryRegister(param, symbols.NewLocalVariableSym(param))
|
||||
}
|
||||
}
|
||||
|
||||
body := node.GetBody()
|
||||
if body != nil {
|
||||
v := newASTBinder(b, node)
|
||||
ast.Walk(v, body)
|
||||
}
|
||||
}
|
||||
|
||||
// astBinder is an AST visitor implementation that understands how to deal with all sorts of node types. It
|
||||
// does not visit children, however, as it relies on the depth-first order walk supplied by the AST package. The
|
||||
// overall purpose of this is to perform validation, and record types and symbols that're needed during evaluation.
|
||||
|
@ -243,8 +222,39 @@ func (a *astBinder) checkObjectLiteral(node *ast.ObjectLiteral) {
|
|||
if node.Type == nil {
|
||||
a.b.registerExprType(node, types.Any)
|
||||
} else {
|
||||
a.b.registerExprType(node, a.b.bindType(node.Type))
|
||||
// TODO: ensure the properties, if any, actually exist on the target object.
|
||||
ty := a.b.bindType(node.Type)
|
||||
a.b.registerExprType(node, ty)
|
||||
|
||||
// Only permit object literals for records and interfaces. Classes have constructors.
|
||||
if !ty.Record() && !ty.Interface() {
|
||||
a.b.Diag().Errorf(errors.ErrorIllegalObjectLiteralType.At(node.Type), ty)
|
||||
} else {
|
||||
// Ensure that all required properties have been supplied, and that they are of the right type.
|
||||
props := make(map[tokens.ClassMemberName]bool)
|
||||
if node.Properties != nil {
|
||||
for _, init := range *node.Properties {
|
||||
sym := a.b.requireClassMember(init.Property, ty, init.Property.Tok)
|
||||
if sym != nil {
|
||||
switch s := sym.(type) {
|
||||
case *symbols.ClassProperty, *symbols.ClassMethod:
|
||||
a.checkExprType(init.Value, s.Type())
|
||||
default:
|
||||
contract.Failf("Unrecognized class member symbol: %v", sym)
|
||||
}
|
||||
props[init.Property.Tok.Name()] = true // record that we've seen this one.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Issue an error about any missing required properties.
|
||||
for name, member := range ty.Members() {
|
||||
if _, has := props[name]; !has {
|
||||
if !member.Optional() && member.Default() == nil {
|
||||
a.b.Diag().Errorf(errors.ErrorMissingRequiredProperty.At(node), name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -146,3 +146,8 @@ var ErrorUnknownJumpLabel = &diag.Diag{
|
|||
ID: 525,
|
||||
Message: "Unknown label '%v' used in the %v statement",
|
||||
}
|
||||
|
||||
var ErrorIllegalObjectLiteralType = &diag.Diag{
|
||||
ID: 526,
|
||||
Message: "The type '%v' may not be used as an object literal type; only records and interfaces are permitted",
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ type Class struct {
|
|||
Parent *Module
|
||||
Extends Type
|
||||
Implements Types
|
||||
Members ClassMemberMap
|
||||
Clmembers ClassMemberMap
|
||||
}
|
||||
|
||||
var _ Symbol = (*Class)(nil)
|
||||
|
@ -22,8 +22,6 @@ var _ Type = (*Class)(nil)
|
|||
var _ ModuleMember = (*Class)(nil)
|
||||
|
||||
func (node *Class) symbol() {}
|
||||
func (node *Class) typesym() {}
|
||||
func (node *Class) moduleMember() {}
|
||||
func (node *Class) Name() tokens.Name { return node.Node.Name.Ident }
|
||||
func (node *Class) Token() tokens.Token {
|
||||
return tokens.Token(
|
||||
|
@ -34,13 +32,15 @@ func (node *Class) Token() tokens.Token {
|
|||
)
|
||||
}
|
||||
func (node *Class) Tree() diag.Diagable { return node.Node }
|
||||
func (node *Class) String() string { return string(node.Name()) }
|
||||
func (node *Class) moduleMember() {}
|
||||
func (node *Class) MemberNode() ast.ModuleMember { return node.Node }
|
||||
|
||||
func (node *Class) typesym() {}
|
||||
func (node *Class) Members() ClassMemberMap { return node.Clmembers }
|
||||
func (node *Class) Sealed() bool { return node.Node.Sealed != nil && *node.Node.Sealed }
|
||||
func (node *Class) Abstract() bool { return node.Node.Abstract != nil && *node.Node.Abstract }
|
||||
func (node *Class) Record() bool { return node.Node.Record != nil && *node.Node.Record }
|
||||
func (node *Class) Interface() bool { return node.Node.Interface != nil && *node.Node.Interface }
|
||||
func (node *Class) String() string { return string(node.Name()) }
|
||||
|
||||
// NewClassSym returns a new Class symbol with the given node, parent, extends, and implements, and empty members.
|
||||
func NewClassSym(node *ast.Class, parent *Module, extends Type, implements Types) *Class {
|
||||
|
@ -49,7 +49,7 @@ func NewClassSym(node *ast.Class, parent *Module, extends Type, implements Types
|
|||
Parent: parent,
|
||||
Extends: extends,
|
||||
Implements: implements,
|
||||
Members: make(ClassMemberMap),
|
||||
Clmembers: make(ClassMemberMap),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,23 +57,29 @@ func NewClassSym(node *ast.Class, parent *Module, extends Type, implements Types
|
|||
type ClassMember interface {
|
||||
Symbol
|
||||
classMember()
|
||||
Optional() bool
|
||||
Default() *interface{}
|
||||
Type() Type
|
||||
MemberNode() ast.ClassMember
|
||||
}
|
||||
|
||||
// ClassMemberMap is a map from a class member's name to its associated symbol.
|
||||
type ClassMemberMap map[tokens.ClassMemberName]ClassMember
|
||||
|
||||
// noClassMembers is a permanently empty class member map for efficient returning of empty ones.
|
||||
var noClassMembers = make(ClassMemberMap)
|
||||
|
||||
// ClassProperty is a fully bound module property symbol.
|
||||
type ClassProperty struct {
|
||||
Node *ast.ClassProperty
|
||||
Parent *Class
|
||||
Typ Type
|
||||
}
|
||||
|
||||
var _ Symbol = (*ClassProperty)(nil)
|
||||
var _ ClassMember = (*ClassProperty)(nil)
|
||||
|
||||
func (node *ClassProperty) symbol() {}
|
||||
func (node *ClassProperty) classMember() {}
|
||||
func (node *ClassProperty) Name() tokens.Name { return node.Node.Name.Ident }
|
||||
func (node *ClassProperty) Token() tokens.Token {
|
||||
return tokens.Token(
|
||||
|
@ -84,14 +90,19 @@ func (node *ClassProperty) Token() tokens.Token {
|
|||
)
|
||||
}
|
||||
func (node *ClassProperty) Tree() diag.Diagable { return node.Node }
|
||||
func (node *ClassProperty) String() string { return string(node.Name()) }
|
||||
func (node *ClassProperty) classMember() {}
|
||||
func (node *ClassProperty) Optional() bool { return node.Node.Optional != nil && *node.Node.Optional }
|
||||
func (node *ClassProperty) Default() *interface{} { return node.Node.Default }
|
||||
func (node *ClassProperty) Type() Type { return node.Typ }
|
||||
func (node *ClassProperty) MemberNode() ast.ClassMember { return node.Node }
|
||||
func (node *ClassProperty) String() string { return string(node.Name()) }
|
||||
|
||||
// NewClassPropertySym returns a new ClassProperty symbol with the given node and parent.
|
||||
func NewClassPropertySym(node *ast.ClassProperty, parent *Class) *ClassProperty {
|
||||
func NewClassPropertySym(node *ast.ClassProperty, parent *Class, typ Type) *ClassProperty {
|
||||
return &ClassProperty{
|
||||
Node: node,
|
||||
Parent: parent,
|
||||
Typ: typ,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,13 +110,13 @@ func NewClassPropertySym(node *ast.ClassProperty, parent *Class) *ClassProperty
|
|||
type ClassMethod struct {
|
||||
Node *ast.ClassMethod
|
||||
Parent *Class
|
||||
Typ *FunctionType
|
||||
}
|
||||
|
||||
var _ Symbol = (*ClassMethod)(nil)
|
||||
var _ ClassMember = (*ClassMethod)(nil)
|
||||
|
||||
func (node *ClassMethod) symbol() {}
|
||||
func (node *ClassMethod) classMember() {}
|
||||
func (node *ClassMethod) Name() tokens.Name { return node.Node.Name.Ident }
|
||||
func (node *ClassMethod) Token() tokens.Token {
|
||||
return tokens.Token(
|
||||
|
@ -116,13 +127,18 @@ func (node *ClassMethod) Token() tokens.Token {
|
|||
)
|
||||
}
|
||||
func (node *ClassMethod) Tree() diag.Diagable { return node.Node }
|
||||
func (node *ClassMethod) String() string { return string(node.Name()) }
|
||||
func (node *ClassMethod) classMember() {}
|
||||
func (node *ClassMethod) Optional() bool { return true }
|
||||
func (node *ClassMethod) Default() *interface{} { return nil }
|
||||
func (node *ClassMethod) Type() Type { return node.Typ }
|
||||
func (node *ClassMethod) MemberNode() ast.ClassMember { return node.Node }
|
||||
func (node *ClassMethod) String() string { return string(node.Name()) }
|
||||
|
||||
// NewClassMethodSym returns a new ClassMethod symbol with the given node and parent.
|
||||
func NewClassMethodSym(node *ast.ClassMethod, parent *Class) *ClassMethod {
|
||||
func NewClassMethodSym(node *ast.ClassMethod, parent *Class, typ *FunctionType) *ClassMethod {
|
||||
return &ClassMethod{
|
||||
Node: node,
|
||||
Parent: parent,
|
||||
Typ: typ,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ var _ Symbol = (*Export)(nil)
|
|||
var _ ModuleMember = (*Export)(nil)
|
||||
|
||||
func (node *Export) symbol() {}
|
||||
func (node *Export) moduleMember() {}
|
||||
func (node *Export) Name() tokens.Name { return node.Node.Name.Ident }
|
||||
func (node *Export) Token() tokens.Token {
|
||||
return tokens.Token(
|
||||
|
@ -76,8 +75,9 @@ func (node *Export) Token() tokens.Token {
|
|||
)
|
||||
}
|
||||
func (node *Export) Tree() diag.Diagable { return node.Node }
|
||||
func (node *Export) String() string { return string(node.Name()) }
|
||||
func (node *Export) moduleMember() {}
|
||||
func (node *Export) MemberNode() ast.ModuleMember { return node.Node }
|
||||
func (node *Export) String() string { return string(node.Name()) }
|
||||
|
||||
// NewExportSym returns a new Export symbol with the given node, parent, and referent symbol.
|
||||
func NewExportSym(node *ast.Export, parent *Module, referent Symbol) *Export {
|
||||
|
@ -92,13 +92,13 @@ func NewExportSym(node *ast.Export, parent *Module, referent Symbol) *Export {
|
|||
type ModuleProperty struct {
|
||||
Node *ast.ModuleProperty
|
||||
Parent *Module
|
||||
Type Type
|
||||
}
|
||||
|
||||
var _ Symbol = (*ModuleProperty)(nil)
|
||||
var _ ModuleMember = (*ModuleProperty)(nil)
|
||||
|
||||
func (node *ModuleProperty) symbol() {}
|
||||
func (node *ModuleProperty) moduleMember() {}
|
||||
func (node *ModuleProperty) Name() tokens.Name { return node.Node.Name.Ident }
|
||||
func (node *ModuleProperty) Token() tokens.Token {
|
||||
return tokens.Token(
|
||||
|
@ -109,14 +109,16 @@ func (node *ModuleProperty) Token() tokens.Token {
|
|||
)
|
||||
}
|
||||
func (node *ModuleProperty) Tree() diag.Diagable { return node.Node }
|
||||
func (node *ModuleProperty) String() string { return string(node.Name()) }
|
||||
func (node *ModuleProperty) moduleMember() {}
|
||||
func (node *ModuleProperty) MemberNode() ast.ModuleMember { return node.Node }
|
||||
func (node *ModuleProperty) String() string { return string(node.Name()) }
|
||||
|
||||
// NewModulePropertySym returns a new ModuleProperty symbol with the given node and parent.
|
||||
func NewModulePropertySym(node *ast.ModuleProperty, parent *Module) *ModuleProperty {
|
||||
func NewModulePropertySym(node *ast.ModuleProperty, parent *Module, typ Type) *ModuleProperty {
|
||||
return &ModuleProperty{
|
||||
Node: node,
|
||||
Parent: parent,
|
||||
Type: typ,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,13 +126,13 @@ func NewModulePropertySym(node *ast.ModuleProperty, parent *Module) *ModulePrope
|
|||
type ModuleMethod struct {
|
||||
Node *ast.ModuleMethod
|
||||
Parent *Module
|
||||
Type *FunctionType
|
||||
}
|
||||
|
||||
var _ Symbol = (*ModuleMethod)(nil)
|
||||
var _ ModuleMember = (*ModuleMethod)(nil)
|
||||
|
||||
func (node *ModuleMethod) symbol() {}
|
||||
func (node *ModuleMethod) moduleMember() {}
|
||||
func (node *ModuleMethod) Name() tokens.Name { return node.Node.Name.Ident }
|
||||
func (node *ModuleMethod) Token() tokens.Token {
|
||||
return tokens.Token(
|
||||
|
@ -141,13 +143,15 @@ func (node *ModuleMethod) Token() tokens.Token {
|
|||
)
|
||||
}
|
||||
func (node *ModuleMethod) Tree() diag.Diagable { return node.Node }
|
||||
func (node *ModuleMethod) String() string { return string(node.Name()) }
|
||||
func (node *ModuleMethod) moduleMember() {}
|
||||
func (node *ModuleMethod) MemberNode() ast.ModuleMember { return node.Node }
|
||||
func (node *ModuleMethod) String() string { return string(node.Name()) }
|
||||
|
||||
// NewModuleMethodSym returns a new ModuleMethod symbol with the given node and parent.
|
||||
func NewModuleMethodSym(node *ast.ModuleMethod, parent *Module) *ModuleMethod {
|
||||
func NewModuleMethodSym(node *ast.ModuleMethod, parent *Module, typ *FunctionType) *ModuleMethod {
|
||||
return &ModuleMethod{
|
||||
Node: node,
|
||||
Parent: parent,
|
||||
Type: typ,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@ import (
|
|||
type Type interface {
|
||||
Symbol
|
||||
typesym()
|
||||
Members() ClassMemberMap // this type's members.
|
||||
Record() bool // true if this is a record type.
|
||||
Interface() bool // true if this is an interface type.
|
||||
}
|
||||
|
||||
// Types is a list of type symbols.
|
||||
|
@ -27,10 +30,13 @@ var _ Symbol = (*PrimitiveType)(nil)
|
|||
var _ Type = (*PrimitiveType)(nil)
|
||||
|
||||
func (node *PrimitiveType) symbol() {}
|
||||
func (node *PrimitiveType) typesym() {}
|
||||
func (node *PrimitiveType) Name() tokens.Name { return tokens.Name(node.Nm) }
|
||||
func (node *PrimitiveType) Token() tokens.Token { return tokens.Token(node.Nm) }
|
||||
func (node *PrimitiveType) Tree() diag.Diagable { return nil }
|
||||
func (node *PrimitiveType) typesym() {}
|
||||
func (node *PrimitiveType) Members() ClassMemberMap { return noClassMembers }
|
||||
func (node *PrimitiveType) Record() bool { return false }
|
||||
func (node *PrimitiveType) Interface() bool { return false }
|
||||
func (node *PrimitiveType) String() string { return string(node.Name()) }
|
||||
|
||||
func NewPrimitiveType(nm tokens.TypeName) *PrimitiveType {
|
||||
|
@ -48,10 +54,13 @@ var _ Symbol = (*PointerType)(nil)
|
|||
var _ Type = (*PointerType)(nil)
|
||||
|
||||
func (node *PointerType) symbol() {}
|
||||
func (node *PointerType) typesym() {}
|
||||
func (node *PointerType) Name() tokens.Name { return tokens.Name(node.Nm) }
|
||||
func (node *PointerType) Token() tokens.Token { return tokens.Token(node.Tok) }
|
||||
func (node *PointerType) Tree() diag.Diagable { return nil }
|
||||
func (node *PointerType) typesym() {}
|
||||
func (node *PointerType) Members() ClassMemberMap { return noClassMembers }
|
||||
func (node *PointerType) Record() bool { return false }
|
||||
func (node *PointerType) Interface() bool { return false }
|
||||
func (node *PointerType) String() string { return string(node.Name()) }
|
||||
|
||||
func NewPointerType(elem Type) *PointerType {
|
||||
|
@ -86,10 +95,13 @@ var _ Symbol = (*ArrayType)(nil)
|
|||
var _ Type = (*ArrayType)(nil)
|
||||
|
||||
func (node *ArrayType) symbol() {}
|
||||
func (node *ArrayType) typesym() {}
|
||||
func (node *ArrayType) Name() tokens.Name { return tokens.Name(node.Nm) }
|
||||
func (node *ArrayType) Token() tokens.Token { return tokens.Token(node.Tok) }
|
||||
func (node *ArrayType) Tree() diag.Diagable { return nil }
|
||||
func (node *ArrayType) typesym() {}
|
||||
func (node *ArrayType) Members() ClassMemberMap { return noClassMembers }
|
||||
func (node *ArrayType) Record() bool { return false }
|
||||
func (node *ArrayType) Interface() bool { return false }
|
||||
func (node *ArrayType) String() string { return string(node.Name()) }
|
||||
|
||||
func NewArrayType(elem Type) *ArrayType {
|
||||
|
@ -125,10 +137,13 @@ var _ Symbol = (*MapType)(nil)
|
|||
var _ Type = (*MapType)(nil)
|
||||
|
||||
func (node *MapType) symbol() {}
|
||||
func (node *MapType) typesym() {}
|
||||
func (node *MapType) Name() tokens.Name { return tokens.Name(node.Nm) }
|
||||
func (node *MapType) Token() tokens.Token { return tokens.Token(node.Tok) }
|
||||
func (node *MapType) Tree() diag.Diagable { return nil }
|
||||
func (node *MapType) typesym() {}
|
||||
func (node *MapType) Members() ClassMemberMap { return noClassMembers }
|
||||
func (node *MapType) Record() bool { return false }
|
||||
func (node *MapType) Interface() bool { return false }
|
||||
func (node *MapType) String() string { return string(node.Name()) }
|
||||
|
||||
func NewMapType(key Type, elem Type) *MapType {
|
||||
|
@ -165,10 +180,13 @@ var _ Symbol = (*FunctionType)(nil)
|
|||
var _ Type = (*FunctionType)(nil)
|
||||
|
||||
func (node *FunctionType) symbol() {}
|
||||
func (node *FunctionType) typesym() {}
|
||||
func (node *FunctionType) Name() tokens.Name { return tokens.Name(node.Nm) }
|
||||
func (node *FunctionType) Token() tokens.Token { return tokens.Token(node.Tok) }
|
||||
func (node *FunctionType) Tree() diag.Diagable { return nil }
|
||||
func (node *FunctionType) typesym() {}
|
||||
func (node *FunctionType) Members() ClassMemberMap { return noClassMembers }
|
||||
func (node *FunctionType) Record() bool { return false }
|
||||
func (node *FunctionType) Interface() bool { return false }
|
||||
func (node *FunctionType) String() string { return string(node.Name()) }
|
||||
|
||||
func NewFunctionType(params []Type, ret Type) *FunctionType {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016 Marapongo, Inc. All rights reserved.
|
||||
|
||||
import {LocalVariable} from "./definitions";
|
||||
import {Identifier, Node, TypeToken} from "./nodes";
|
||||
import {ClassMemberToken, Identifier, Node, TypeToken} from "./nodes";
|
||||
import * as statements from "./statements";
|
||||
|
||||
import * as symbols from "../symbols";
|
||||
|
@ -67,7 +67,7 @@ export type ObjectLiteralKind = "ObjectLiteral";
|
|||
// An object literal property initializer.
|
||||
export interface ObjectLiteralProperty extends Node {
|
||||
kind: ObjectLiteralPropertyKind;
|
||||
name: Identifier; // the property being initialized.
|
||||
property: ClassMemberToken; // the property being initialized.
|
||||
value: Expression; // the expression value to store into the property.
|
||||
}
|
||||
export const objectLiteralPropertyKind = "ObjectLiteralProperty";
|
||||
|
|
|
@ -20,6 +20,7 @@ export interface Node {
|
|||
export type NodeKind =
|
||||
IdentifierKind |
|
||||
TokenKind |
|
||||
ClassMemberTokenKind |
|
||||
ModuleTokenKind |
|
||||
TypeTokenKind |
|
||||
|
||||
|
@ -82,6 +83,13 @@ export interface Token extends Node {
|
|||
export const tokenKind = "Token";
|
||||
export type TokenKind = "Token";
|
||||
|
||||
export interface ClassMemberToken extends Node {
|
||||
kind: ClassMemberTokenKind;
|
||||
tok: symbols.ClassMemberToken;
|
||||
}
|
||||
export const classMemberTokenKind = "ClassMemberToken";
|
||||
export type ClassMemberTokenKind = "ClassMemberToken";
|
||||
|
||||
export interface ModuleToken extends Node {
|
||||
kind: ModuleTokenKind;
|
||||
tok: symbols.ModuleToken;
|
||||
|
|
|
@ -1781,9 +1781,13 @@ export class Transformer {
|
|||
}
|
||||
|
||||
private transformObjectLiteralPropertyAssignment(node: ts.PropertyAssignment): ast.ObjectLiteralProperty {
|
||||
let pname: ast.Identifier = this.transformPropertyName(node.name);
|
||||
return this.withLocation(node, <ast.ObjectLiteralProperty>{
|
||||
kind: ast.objectLiteralPropertyKind,
|
||||
name: this.transformPropertyName(node.name),
|
||||
property: <ast.ClassMemberToken>{
|
||||
kind: ast.classMemberTokenKind,
|
||||
tok: pname.ident,
|
||||
},
|
||||
value: this.transformExpression(node.initializer),
|
||||
});
|
||||
}
|
||||
|
@ -1793,7 +1797,10 @@ export class Transformer {
|
|||
let name: ast.Identifier = this.transformIdentifier(node.name);
|
||||
return this.withLocation(node, <ast.ObjectLiteralProperty>{
|
||||
kind: ast.objectLiteralPropertyKind,
|
||||
name: name,
|
||||
property: <ast.ClassMemberToken>{
|
||||
kind: ast.classMemberTokenKind,
|
||||
tok: name.ident,
|
||||
},
|
||||
value: this.withLocation(node.name, <ast.LoadLocationExpression>{
|
||||
kind: ast.loadLocationExpressionKind,
|
||||
name: name,
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
// Tokens.
|
||||
export type Token = string; // a valid symbol token.
|
||||
export type ModuleToken = Token; // a symbol token that resolves to a module.
|
||||
export type ModuleMemberToken = Token; // a symbol token that resolves to a module member.
|
||||
export type ClassMemberToken = Token; // a symbol token that resolves to a class member.
|
||||
export type TypeToken = Token; // a symbol token that resolves to a type.
|
||||
export type VariableToken = Token; // a symbol token that resolves to a variable.
|
||||
export type FunctionToken = Token; // a symbol token that resolves to a function.
|
||||
|
|
Loading…
Reference in a new issue