Bind object initializers

This commit is contained in:
joeduffy 2017-01-23 12:51:13 -08:00
parent a7ccc1b052
commit d56f640d5f
16 changed files with 220 additions and 108 deletions

View file

@ -104,8 +104,8 @@ const ObjectLiteralKind NodeKind = "ObjectLiteral"
// ObjectLiteralProperty initializes a single object literal property.
type ObjectLiteralProperty struct {
NodeValue
Name *Identifier `json:"name"` // the property to initialize.
Value Expression `json:"value"` // the expression whose value to store into the property.
Property *ClassMemberToken `json:"property"` // the property to initialize.
Value Expression `json:"value"` // the expression whose value to store into the property.
}
var _ Node = (*ObjectLiteralProperty)(nil)

View file

@ -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

View file

@ -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 {

View file

@ -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
}

View file

@ -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) {

View 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)
}
}

View file

@ -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)

View file

@ -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)
}
}
}
}
}
}

View file

@ -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",
}

View file

@ -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) 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) 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,
}
}

View file

@ -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,
}
}

View file

@ -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.
@ -26,12 +29,15 @@ type PrimitiveType struct {
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) String() string { return string(node.Name()) }
func (node *PrimitiveType) symbol() {}
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 {
return &PrimitiveType{nm}
@ -47,12 +53,15 @@ type PointerType struct {
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) String() string { return string(node.Name()) }
func (node *PointerType) symbol() {}
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 {
nm := newPointerTypeName(elem)
@ -85,12 +94,15 @@ type ArrayType struct {
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) String() string { return string(node.Name()) }
func (node *ArrayType) symbol() {}
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 {
nm := newArrayTypeName(elem)
@ -124,12 +136,15 @@ type MapType struct {
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) String() string { return string(node.Name()) }
func (node *MapType) symbol() {}
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 {
nm := newMapTypeName(key, elem)
@ -164,12 +179,15 @@ type FunctionType struct {
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) String() string { return string(node.Name()) }
func (node *FunctionType) symbol() {}
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 {
nm := newFunctionTypeName(params, ret)

View file

@ -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";
@ -66,9 +66,9 @@ export type ObjectLiteralKind = "ObjectLiteral";
// An object literal property initializer.
export interface ObjectLiteralProperty extends Node {
kind: ObjectLiteralPropertyKind;
name: Identifier; // the property being initialized.
value: Expression; // the expression value to store into the property.
kind: ObjectLiteralPropertyKind;
property: ClassMemberToken; // the property being initialized.
value: Expression; // the expression value to store into the property.
}
export const objectLiteralPropertyKind = "ObjectLiteralProperty";
export type ObjectLiteralPropertyKind = "ObjectLiteralProperty";

View file

@ -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;

View file

@ -1781,10 +1781,14 @@ 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),
value: this.transformExpression(node.initializer),
kind: ast.objectLiteralPropertyKind,
property: <ast.ClassMemberToken>{
kind: ast.classMemberTokenKind,
tok: pname.ident,
},
value: this.transformExpression(node.initializer),
});
}
@ -1792,9 +1796,12 @@ export class Transformer {
node: ts.ShorthandPropertyAssignment): ast.ObjectLiteralProperty {
let name: ast.Identifier = this.transformIdentifier(node.name);
return this.withLocation(node, <ast.ObjectLiteralProperty>{
kind: ast.objectLiteralPropertyKind,
name: name,
value: this.withLocation(node.name, <ast.LoadLocationExpression>{
kind: ast.objectLiteralPropertyKind,
property: <ast.ClassMemberToken>{
kind: ast.classMemberTokenKind,
tok: name.ident,
},
value: this.withLocation(node.name, <ast.LoadLocationExpression>{
kind: ast.loadLocationExpressionKind,
name: name,
}),

View file

@ -1,11 +1,13 @@
// Copyright 2016 Marapongo, Inc. All rights reserved.
// Tokens.
export type Token = string; // a valid symbol token.
export type ModuleToken = Token; // a symbol token that resolves to a module.
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.
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.
export const moduleSep = ":"; // a character delimiting module / member names (e.g., "module:member").
export const selfModule: ModuleToken = "."; // a self-referential token for the current module.