Skip to content

Commit

Permalink
Implemented classes (including private elements). Closes dop251#349.
Browse files Browse the repository at this point in the history
  • Loading branch information
dop251 committed Jul 21, 2022
1 parent 38a3647 commit 0b5d210
Show file tree
Hide file tree
Showing 23 changed files with 4,374 additions and 570 deletions.
97 changes: 97 additions & 0 deletions ast/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ type (
Identifier Identifier
}

PrivateDotExpression struct {
Left Expression
Identifier PrivateIdentifier
}

OptionalChain struct {
Expression
}
Expand All @@ -136,6 +141,15 @@ type (
DeclarationList []*VariableDeclaration
}

ClassLiteral struct {
Class file.Idx
RightBrace file.Idx
Name *Identifier
SuperClass Expression
Body []ClassElement
Source string
}

ConciseBody interface {
Node
_conciseBody()
Expand All @@ -158,6 +172,10 @@ type (
Idx file.Idx
}

PrivateIdentifier struct {
Identifier
}

NewExpression struct {
New file.Idx
Callee Expression
Expand Down Expand Up @@ -254,6 +272,10 @@ type (
Idx file.Idx
}

SuperExpression struct {
Idx file.Idx
}

UnaryExpression struct {
Operator token.Token
Idx file.Idx // If a prefix operation
Expand All @@ -278,7 +300,9 @@ func (*BracketExpression) _expressionNode() {}
func (*CallExpression) _expressionNode() {}
func (*ConditionalExpression) _expressionNode() {}
func (*DotExpression) _expressionNode() {}
func (*PrivateDotExpression) _expressionNode() {}
func (*FunctionLiteral) _expressionNode() {}
func (*ClassLiteral) _expressionNode() {}
func (*ArrowFunctionLiteral) _expressionNode() {}
func (*Identifier) _expressionNode() {}
func (*NewExpression) _expressionNode() {}
Expand All @@ -290,6 +314,7 @@ func (*SequenceExpression) _expressionNode() {}
func (*StringLiteral) _expressionNode() {}
func (*TemplateLiteral) _expressionNode() {}
func (*ThisExpression) _expressionNode() {}
func (*SuperExpression) _expressionNode() {}
func (*UnaryExpression) _expressionNode() {}
func (*MetaProperty) _expressionNode() {}
func (*ObjectPattern) _expressionNode() {}
Expand Down Expand Up @@ -442,6 +467,10 @@ type (
FunctionDeclaration struct {
Function *FunctionLiteral
}

ClassDeclaration struct {
Class *ClassLiteral
}
)

// _statementNode
Expand Down Expand Up @@ -469,6 +498,7 @@ func (*WhileStatement) _statementNode() {}
func (*WithStatement) _statementNode() {}
func (*LexicalDeclaration) _statementNode() {}
func (*FunctionDeclaration) _statementNode() {}
func (*ClassDeclaration) _statementNode() {}

// =========== //
// Declaration //
Expand All @@ -479,6 +509,33 @@ type (
Var file.Idx
List []*Binding
}

ClassElement interface {
Node
_classElement()
}

FieldDefinition struct {
Idx file.Idx
Key Expression
Initializer Expression
Static bool
}

MethodDefinition struct {
Idx file.Idx
Key Expression
Kind PropertyKind // "method", "get" or "set"
Body *FunctionLiteral
Static bool
}

ClassStaticBlock struct {
Static file.Idx
Block *BlockStatement
Source string
DeclarationList []*VariableDeclaration
}
)

type (
Expand All @@ -500,6 +557,7 @@ type (
}

ForInto interface {
Node
_forInto()
}

Expand Down Expand Up @@ -543,6 +601,10 @@ func (*Identifier) _bindingTarget() {}
func (*BlockStatement) _conciseBody() {}
func (*ExpressionBody) _conciseBody() {}

func (*FieldDefinition) _classElement() {}
func (*MethodDefinition) _classElement() {}
func (*ClassStaticBlock) _classElement() {}

// ==== //
// Node //
// ==== //
Expand Down Expand Up @@ -570,7 +632,9 @@ func (self *BracketExpression) Idx0() file.Idx { return self.Left.Idx0() }
func (self *CallExpression) Idx0() file.Idx { return self.Callee.Idx0() }
func (self *ConditionalExpression) Idx0() file.Idx { return self.Test.Idx0() }
func (self *DotExpression) Idx0() file.Idx { return self.Left.Idx0() }
func (self *PrivateDotExpression) Idx0() file.Idx { return self.Left.Idx0() }
func (self *FunctionLiteral) Idx0() file.Idx { return self.Function }
func (self *ClassLiteral) Idx0() file.Idx { return self.Class }
func (self *ArrowFunctionLiteral) Idx0() file.Idx { return self.Start }
func (self *Identifier) Idx0() file.Idx { return self.Idx }
func (self *NewExpression) Idx0() file.Idx { return self.New }
Expand All @@ -582,6 +646,7 @@ func (self *SequenceExpression) Idx0() file.Idx { return self.Sequence[0].Idx
func (self *StringLiteral) Idx0() file.Idx { return self.Idx }
func (self *TemplateLiteral) Idx0() file.Idx { return self.OpenQuote }
func (self *ThisExpression) Idx0() file.Idx { return self.Idx }
func (self *SuperExpression) Idx0() file.Idx { return self.Idx }
func (self *UnaryExpression) Idx0() file.Idx { return self.Idx }
func (self *MetaProperty) Idx0() file.Idx { return self.Idx }

Expand Down Expand Up @@ -609,13 +674,22 @@ func (self *WhileStatement) Idx0() file.Idx { return self.While }
func (self *WithStatement) Idx0() file.Idx { return self.With }
func (self *LexicalDeclaration) Idx0() file.Idx { return self.Idx }
func (self *FunctionDeclaration) Idx0() file.Idx { return self.Function.Idx0() }
func (self *ClassDeclaration) Idx0() file.Idx { return self.Class.Idx0() }
func (self *Binding) Idx0() file.Idx { return self.Target.Idx0() }

func (self *ForLoopInitializerVarDeclList) Idx0() file.Idx { return self.List[0].Idx0() }
func (self *PropertyShort) Idx0() file.Idx { return self.Name.Idx }
func (self *PropertyKeyed) Idx0() file.Idx { return self.Key.Idx0() }
func (self *ExpressionBody) Idx0() file.Idx { return self.Expression.Idx0() }

func (self *FieldDefinition) Idx0() file.Idx { return self.Idx }
func (self *MethodDefinition) Idx0() file.Idx { return self.Idx }
func (self *ClassStaticBlock) Idx0() file.Idx { return self.Static }

func (self *ForDeclaration) Idx0() file.Idx { return self.Idx }
func (self *ForIntoVar) Idx0() file.Idx { return self.Binding.Idx0() }
func (self *ForIntoExpression) Idx0() file.Idx { return self.Expression.Idx0() }

// ==== //
// Idx1 //
// ==== //
Expand All @@ -630,7 +704,9 @@ func (self *BracketExpression) Idx1() file.Idx { return self.RightBracket +
func (self *CallExpression) Idx1() file.Idx { return self.RightParenthesis + 1 }
func (self *ConditionalExpression) Idx1() file.Idx { return self.Test.Idx1() }
func (self *DotExpression) Idx1() file.Idx { return self.Identifier.Idx1() }
func (self *PrivateDotExpression) Idx1() file.Idx { return self.Identifier.Idx1() }
func (self *FunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() }
func (self *ClassLiteral) Idx1() file.Idx { return self.RightBrace + 1 }
func (self *ArrowFunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() }
func (self *Identifier) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Name)) }
func (self *NewExpression) Idx1() file.Idx {
Expand All @@ -649,6 +725,7 @@ func (self *SequenceExpression) Idx1() file.Idx { return self.Sequence[len(self.
func (self *StringLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
func (self *TemplateLiteral) Idx1() file.Idx { return self.CloseQuote + 1 }
func (self *ThisExpression) Idx1() file.Idx { return self.Idx + 4 }
func (self *SuperExpression) Idx1() file.Idx { return self.Idx + 5 }
func (self *UnaryExpression) Idx1() file.Idx {
if self.Postfix {
return self.Operand.Idx1() + 2 // ++ --
Expand Down Expand Up @@ -696,6 +773,7 @@ func (self *WhileStatement) Idx1() file.Idx { return self.Body.Idx1() }
func (self *WithStatement) Idx1() file.Idx { return self.Body.Idx1() }
func (self *LexicalDeclaration) Idx1() file.Idx { return self.List[len(self.List)-1].Idx1() }
func (self *FunctionDeclaration) Idx1() file.Idx { return self.Function.Idx1() }
func (self *ClassDeclaration) Idx1() file.Idx { return self.Class.Idx1() }
func (self *Binding) Idx1() file.Idx {
if self.Initializer != nil {
return self.Initializer.Idx1()
Expand All @@ -715,3 +793,22 @@ func (self *PropertyShort) Idx1() file.Idx {
func (self *PropertyKeyed) Idx1() file.Idx { return self.Value.Idx1() }

func (self *ExpressionBody) Idx1() file.Idx { return self.Expression.Idx1() }

func (self *FieldDefinition) Idx1() file.Idx {
if self.Initializer != nil {
return self.Initializer.Idx1()
}
return self.Key.Idx1()
}

func (self *MethodDefinition) Idx1() file.Idx {
return self.Body.Idx1()
}

func (self *ClassStaticBlock) Idx1() file.Idx {
return self.Block.Idx1()
}

func (self *ForDeclaration) Idx1() file.Idx { return self.Target.Idx1() }
func (self *ForIntoVar) Idx1() file.Idx { return self.Binding.Idx1() }
func (self *ForIntoExpression) Idx1() file.Idx { return self.Expression.Idx1() }
23 changes: 14 additions & 9 deletions builtin_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (r *Runtime) builtin_Function(args []Value, proto *Object) *Object {
}
sb.WriteString(asciiString("\n})"))

ret := r.toObject(r.eval(sb.String(), false, false, _undefined))
ret := r.toObject(r.eval(sb.String(), false, false))
ret.self.setProto(proto, true)
return ret
}
Expand All @@ -32,10 +32,12 @@ func (r *Runtime) functionproto_toString(call FunctionCall) Value {
obj := r.toObject(call.This)
repeat:
switch f := obj.self.(type) {
case *methodFuncObject:
return newStringValue(f.src)
case *funcObject:
return newStringValue(f.src)
case *classFuncObject:
return newStringValue(f.src)
case *methodFuncObject:
return newStringValue(f.src)
case *arrowFuncObject:
return newStringValue(f.src)
case *nativeFuncObject:
Expand All @@ -48,7 +50,7 @@ repeat:
case *proxyObject:
repeat2:
switch c := f.target.self.(type) {
case *methodFuncObject, *funcObject, *arrowFuncObject, *nativeFuncObject, *boundFuncObject:
case *classFuncObject, *methodFuncObject, *funcObject, *arrowFuncObject, *nativeFuncObject, *boundFuncObject:
return asciiString("function () { [native code] }")
case *lazyObject:
f.target.self = c.create(obj)
Expand Down Expand Up @@ -126,7 +128,7 @@ func (r *Runtime) boundCallable(target func(FunctionCall) Value, boundArgs []Val
}
}

func (r *Runtime) boundConstruct(target func([]Value, *Object) *Object, boundArgs []Value) func([]Value, *Object) *Object {
func (r *Runtime) boundConstruct(f *Object, target func([]Value, *Object) *Object, boundArgs []Value) func([]Value, *Object) *Object {
if target == nil {
return nil
}
Expand All @@ -137,7 +139,9 @@ func (r *Runtime) boundConstruct(target func([]Value, *Object) *Object, boundArg
}
return func(fargs []Value, newTarget *Object) *Object {
a := append(args, fargs...)
copy(a, args)
if newTarget == f {
newTarget = nil
}
return target(a, newTarget)
}
}
Expand Down Expand Up @@ -185,12 +189,13 @@ lenNotInt:
}

v := &Object{runtime: r}

ff := r.newNativeFuncObj(v, r.boundCallable(fcall, call.Arguments), r.boundConstruct(construct, call.Arguments), nameStr.string(), nil, l)
v.self = &boundFuncObject{
ff := r.newNativeFuncAndConstruct(v, r.boundCallable(fcall, call.Arguments), r.boundConstruct(v, construct, call.Arguments), nil, nameStr.string(), l)
bf := &boundFuncObject{
nativeFuncObject: *ff,
wrapped: obj,
}
bf.prototype = obj.self.proto()
v.self = bf

return v
}
Expand Down
11 changes: 8 additions & 3 deletions builtin_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import (
"fmt"
)

func (r *Runtime) builtin_Object(args []Value, proto *Object) *Object {
func (r *Runtime) builtin_Object(args []Value, newTarget *Object) *Object {
if newTarget != nil && newTarget != r.global.Object {
proto := r.getPrototypeFromCtor(newTarget, nil, r.global.ObjectPrototype)
return r.newBaseObject(proto, classObject).val
}
if len(args) > 0 {
arg := args[0]
if arg != _undefined && arg != _null {
return arg.ToObject(r)
}
}
return r.newBaseObject(proto, classObject).val
return r.NewObject()
}

func (r *Runtime) object_getPrototypeOf(call FunctionCall) Value {
Expand Down Expand Up @@ -566,7 +570,8 @@ func (r *Runtime) initObject() {
Configurable: FLAG_TRUE,
}, true)

r.global.Object = r.newNativeFuncConstruct(r.builtin_Object, classObject, r.global.ObjectPrototype, 1)
r.global.Object = r.newNativeConstructOnly(nil, r.builtin_Object, r.global.ObjectPrototype, "Object", 1).val
r.global.ObjectPrototype.self._putProp("constructor", r.global.Object, true, false, true)
o = r.global.Object.self
o._putProp("assign", r.newNativeFunc(r.object_assign, nil, "assign", nil, 2), true, false, true)
o._putProp("defineProperty", r.newNativeFunc(r.object_defineProperty, nil, "defineProperty", nil, 3), true, false, true)
Expand Down
Loading

0 comments on commit 0b5d210

Please sign in to comment.