Skip to content

Commit

Permalink
Implemented generators (only synchronous so far). Closes dop251#436
Browse files Browse the repository at this point in the history
  • Loading branch information
dop251 committed Feb 1, 2023
1 parent 78b9802 commit 9343cf0
Show file tree
Hide file tree
Showing 29 changed files with 933 additions and 172 deletions.
4 changes: 2 additions & 2 deletions array.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ func (r *Runtime) createArrayIterator(iterObj *Object, kind iterationKind) Value
obj: iterObj,
kind: kind,
}
ai.class = classArrayIterator
ai.class = classObject
ai.val = o
ai.extensible = true
o.self = ai
ai.prototype = r.global.ArrayIteratorPrototype
ai.prototype = r.getArrayIteratorPrototype()
ai.init()

return o
Expand Down
17 changes: 16 additions & 1 deletion ast/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ type (
_pattern()
}

YieldExpression struct {
Yield file.Idx
Argument Expression
Delegate bool
}

AwaitExpression struct {
Await file.Idx
Argument Expression
Expand Down Expand Up @@ -144,7 +150,7 @@ type (

DeclarationList []*VariableDeclaration

Async bool
Async, Generator bool
}

ClassLiteral struct {
Expand Down Expand Up @@ -300,6 +306,7 @@ type (

func (*ArrayLiteral) _expressionNode() {}
func (*AssignExpression) _expressionNode() {}
func (*YieldExpression) _expressionNode() {}
func (*AwaitExpression) _expressionNode() {}
func (*BadExpression) _expressionNode() {}
func (*BinaryExpression) _expressionNode() {}
Expand Down Expand Up @@ -634,6 +641,7 @@ type Program struct {

func (self *ArrayLiteral) Idx0() file.Idx { return self.LeftBracket }
func (self *ArrayPattern) Idx0() file.Idx { return self.LeftBracket }
func (self *YieldExpression) Idx0() file.Idx { return self.Yield }
func (self *AwaitExpression) Idx0() file.Idx { return self.Await }
func (self *ObjectPattern) Idx0() file.Idx { return self.LeftBrace }
func (self *ParameterList) Idx0() file.Idx { return self.Opening }
Expand Down Expand Up @@ -839,6 +847,13 @@ func (self *ClassStaticBlock) Idx1() file.Idx {
return self.Block.Idx1()
}

func (self *YieldExpression) Idx1() file.Idx {
if self.Argument != nil {
return self.Argument.Idx1()
}
return self.Yield + 5
}

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() }
20 changes: 12 additions & 8 deletions builtin_array.go
Original file line number Diff line number Diff line change
Expand Up @@ -1468,7 +1468,7 @@ func (r *Runtime) createArray(val *Object) objectImpl {
}

func (r *Runtime) createArrayIterProto(val *Object) objectImpl {
o := newBaseObjectObj(val, r.global.IteratorPrototype, classObject)
o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)

o._putProp("next", r.newNativeFunc(r.arrayIterProto_next, nil, "next", nil, 0), true, false, true)
o._putSym(SymToStringTag, valueProp(asciiString(classArrayIterator), false, false, true))
Expand All @@ -1480,19 +1480,23 @@ func (r *Runtime) initArray() {
r.global.arrayValues = r.newNativeFunc(r.arrayproto_values, nil, "values", nil, 0)
r.global.arrayToString = r.newNativeFunc(r.arrayproto_toString, nil, "toString", nil, 0)

r.global.ArrayIteratorPrototype = r.newLazyObject(r.createArrayIterProto)
//r.global.ArrayPrototype = r.newArray(r.global.ObjectPrototype).val
//o := r.global.ArrayPrototype.self
r.global.ArrayPrototype = r.newLazyObject(r.createArrayProto)

//r.global.Array = r.newNativeFuncConstruct(r.builtin_newArray, "Array", r.global.ArrayPrototype, 1)
//o = r.global.Array.self
//o._putProp("isArray", r.newNativeFunc(r.array_isArray, nil, "isArray", nil, 1), true, false, true)
r.global.Array = r.newLazyObject(r.createArray)

r.addToGlobal("Array", r.global.Array)
}

func (r *Runtime) getArrayIteratorPrototype() *Object {
var o *Object
if o = r.global.ArrayIteratorPrototype; o == nil {
o = &Object{runtime: r}
r.global.ArrayIteratorPrototype = o
o.self = r.createArrayIterProto(o)
}
return o

}

type sortable interface {
sortLen() int
sortGet(int) Value
Expand Down
2 changes: 1 addition & 1 deletion builtin_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (r *Runtime) builtin_Error(args []Value, proto *Object) *Object {
}

func (r *Runtime) builtin_AggregateError(args []Value, proto *Object) *Object {
obj := r.newErrorObject(proto, classAggError)
obj := r.newErrorObject(proto, classError)
if len(args) > 1 && args[1] != nil && args[1] != _undefined {
obj._putProp("message", args[1].toString(), true, false, true)
}
Expand Down
130 changes: 120 additions & 10 deletions builtin_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ import (
"math"
)

func (r *Runtime) functionCtor(args []Value, proto *Object, async bool) *Object {
func (r *Runtime) functionCtor(args []Value, proto *Object, async, generator bool) *Object {
var sb valueStringBuilder
if async {
sb.WriteString(asciiString("(async function anonymous("))
if generator {
sb.WriteString(asciiString("(async function* anonymous("))
} else {
sb.WriteString(asciiString("(async function anonymous("))
}
} else {
sb.WriteString(asciiString("(function anonymous("))
if generator {
sb.WriteString(asciiString("(function* anonymous("))
} else {
sb.WriteString(asciiString("(function anonymous("))
}
}
if len(args) > 1 {
ar := args[:len(args)-1]
Expand All @@ -32,11 +40,15 @@ func (r *Runtime) functionCtor(args []Value, proto *Object, async bool) *Object
}

func (r *Runtime) builtin_Function(args []Value, proto *Object) *Object {
return r.functionCtor(args, proto, false)
return r.functionCtor(args, proto, false, false)
}

func (r *Runtime) builtin_asyncFunction(args []Value, proto *Object) *Object {
return r.functionCtor(args, proto, true)
return r.functionCtor(args, proto, true, false)
}

func (r *Runtime) builtin_generatorFunction(args []Value, proto *Object) *Object {
return r.functionCtor(args, proto, false, true)
}

func (r *Runtime) functionproto_toString(call FunctionCall) Value {
Expand Down Expand Up @@ -221,20 +233,118 @@ func (r *Runtime) createAsyncFunctionProto(val *Object) objectImpl {
}
o.init()

o._putProp("constructor", r.global.AsyncFunction, true, false, true)
o._putProp("constructor", r.getAsyncFunction(), true, false, true)

o._putSym(SymToStringTag, valueProp(asciiString(classAsyncFunction), false, false, true))

return o
}

func (r *Runtime) getAsyncFunctionPrototype() *Object {
var o *Object
if o = r.global.AsyncFunctionPrototype; o == nil {
o = r.newLazyObject(r.createAsyncFunctionProto)
r.global.AsyncFunctionPrototype = o
}
return o
}

func (r *Runtime) createAsyncFunction(val *Object) objectImpl {
o := r.newNativeFuncConstructObj(val, r.builtin_asyncFunction, "AsyncFunction", r.global.AsyncFunctionPrototype, 1)
o := r.newNativeFuncConstructObj(val, r.builtin_asyncFunction, "AsyncFunction", r.getAsyncFunctionPrototype(), 1)

return o
}

func (r *Runtime) getAsyncFunction() *Object {
var o *Object
if o = r.global.AsyncFunction; o == nil {
o = &Object{runtime: r}
r.global.AsyncFunction = o
o.self = r.createAsyncFunction(o)
}
return o
}

func (r *Runtime) initAsyncFunction() {
r.global.AsyncFunctionPrototype = r.newLazyObject(r.createAsyncFunctionProto)
r.global.AsyncFunction = r.newLazyObject(r.createAsyncFunction)
func (r *Runtime) builtin_genproto_next(call FunctionCall) Value {
if o, ok := call.This.(*Object); ok {
if gen, ok := o.self.(*generatorObject); ok {
return gen.next(call.Argument(0))
}
}
panic(r.NewTypeError("Method [Generator].prototype.next called on incompatible receiver"))
}

func (r *Runtime) builtin_genproto_return(call FunctionCall) Value {
if o, ok := call.This.(*Object); ok {
if gen, ok := o.self.(*generatorObject); ok {
return gen._return(call.Argument(0))
}
}
panic(r.NewTypeError("Method [Generator].prototype.return called on incompatible receiver"))
}

func (r *Runtime) builtin_genproto_throw(call FunctionCall) Value {
if o, ok := call.This.(*Object); ok {
if gen, ok := o.self.(*generatorObject); ok {
return gen.throw(call.Argument(0))
}
}
panic(r.NewTypeError("Method [Generator].prototype.throw called on incompatible receiver"))
}

func (r *Runtime) createGeneratorFunctionProto(val *Object) objectImpl {
o := newBaseObjectObj(val, r.global.FunctionPrototype, classObject)

o._putProp("constructor", r.getGeneratorFunction(), false, false, true)
o._putProp("prototype", r.getGeneratorPrototype(), false, false, true)
o._putSym(SymToStringTag, valueProp(asciiString(classGeneratorFunction), false, false, true))

return o
}

func (r *Runtime) getGeneratorFunctionPrototype() *Object {
var o *Object
if o = r.global.GeneratorFunctionPrototype; o == nil {
o = r.newLazyObject(r.createGeneratorFunctionProto)
r.global.GeneratorFunctionPrototype = o
}
return o
}

func (r *Runtime) createGeneratorFunction(val *Object) objectImpl {
o := r.newNativeFuncConstructObj(val, r.builtin_generatorFunction, "GeneratorFunction", r.getGeneratorFunctionPrototype(), 1)
return o
}

func (r *Runtime) getGeneratorFunction() *Object {
var o *Object
if o = r.global.GeneratorFunction; o == nil {
o = &Object{runtime: r}
r.global.GeneratorFunction = o
o.self = r.createGeneratorFunction(o)
}
return o
}

func (r *Runtime) createGeneratorProto(val *Object) objectImpl {
o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)

o._putProp("constructor", r.getGeneratorFunctionPrototype(), false, false, true)
o._putProp("next", r.newNativeFunc(r.builtin_genproto_next, nil, "next", nil, 1), true, false, true)
o._putProp("return", r.newNativeFunc(r.builtin_genproto_return, nil, "return", nil, 1), true, false, true)
o._putProp("throw", r.newNativeFunc(r.builtin_genproto_throw, nil, "throw", nil, 1), true, false, true)

o._putSym(SymToStringTag, valueProp(asciiString(classGenerator), false, false, true))

return o
}

func (r *Runtime) getGeneratorPrototype() *Object {
var o *Object
if o = r.global.GeneratorPrototype; o == nil {
o = &Object{runtime: r}
r.global.GeneratorPrototype = o
o.self = r.createGeneratorProto(o)
}
return o
}
2 changes: 1 addition & 1 deletion builtin_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ func (ctx *_builtinJSON_stringifyContext) quote(str valueString) {
}

func (r *Runtime) initJSON() {
JSON := r.newBaseObject(r.global.ObjectPrototype, "JSON")
JSON := r.newBaseObject(r.global.ObjectPrototype, classObject)
JSON._putProp("parse", r.newNativeFunc(r.builtinJSON_parse, nil, "parse", nil, 2), true, false, true)
JSON._putProp("stringify", r.newNativeFunc(r.builtinJSON_stringify, nil, "stringify", nil, 3), true, false, true)
JSON._putSym(SymToStringTag, valueProp(asciiString(classJSON), false, false, true))
Expand Down
18 changes: 14 additions & 4 deletions builtin_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ func (r *Runtime) builtin_newMap(args []Value, newTarget *Object) *Object {
o := &Object{runtime: r}

mo := &mapObject{}
mo.class = classMap
mo.class = classObject
mo.val = o
mo.extensible = true
o.self = mo
Expand Down Expand Up @@ -249,11 +249,11 @@ func (r *Runtime) createMapIterator(mapValue Value, kind iterationKind) Value {
iter: mapObj.m.newIter(),
kind: kind,
}
mi.class = classMapIterator
mi.class = classObject
mi.val = o
mi.extensible = true
o.self = mi
mi.prototype = r.global.MapIteratorPrototype
mi.prototype = r.getMapIteratorPrototype()
mi.init()

return o
Expand Down Expand Up @@ -303,14 +303,24 @@ func (r *Runtime) createMap(val *Object) objectImpl {
}

func (r *Runtime) createMapIterProto(val *Object) objectImpl {
o := newBaseObjectObj(val, r.global.IteratorPrototype, classObject)
o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)

o._putProp("next", r.newNativeFunc(r.mapIterProto_next, nil, "next", nil, 0), true, false, true)
o._putSym(SymToStringTag, valueProp(asciiString(classMapIterator), false, false, true))

return o
}

func (r *Runtime) getMapIteratorPrototype() *Object {
var o *Object
if o = r.global.MapIteratorPrototype; o == nil {
o = &Object{runtime: r}
r.global.MapIteratorPrototype = o
o.self = r.createMapIterProto(o)
}
return o
}

func (r *Runtime) initMap() {
r.global.MapIteratorPrototype = r.newLazyObject(r.createMapIterProto)

Expand Down
2 changes: 1 addition & 1 deletion builtin_math.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ func (r *Runtime) math_trunc(call FunctionCall) Value {

func (r *Runtime) createMath(val *Object) objectImpl {
m := &baseObject{
class: classMath,
class: classObject,
val: val,
extensible: true,
prototype: r.global.ObjectPrototype,
Expand Down
2 changes: 1 addition & 1 deletion builtin_promise.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func (r *Runtime) newPromise(proto *Object) *Promise {
o := &Object{runtime: r}

po := &Promise{}
po.class = classPromise
po.class = classObject
po.val = o
po.extensible = true
o.self = po
Expand Down
Loading

0 comments on commit 9343cf0

Please sign in to comment.