ref: f5cc6fbe3a7bcf8bdb002c646ddd519014afafd2
dir: /module/ecmascript.m/
ESHostobj: module { # # extensible interface for adding host objects # # any implementation must obey the rules of the interpreter. # it is an error to return bogus values, and may cause # the interpreter to crash. # # get/put must return/set the value of property in o # # canput and hasproperty return es->true or es->false # # defaultval must return a primitive (non-object) value. # this means it can't return a String object, etc. # # call gets the caller's execution context in ex. # the new this value is passed as an argument, # but no new scopechain is allocated # it returns a reference, which is typically just a value # # construct should make up a new object # get: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; put: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string, val: ref Ecmascript->Val); canput: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; hasproperty: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; delete: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string); defaultval: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, tyhint: int): ref Ecmascript->Val; call: fn(ex: ref Ecmascript->Exec, func, this: ref Ecmascript->Obj, args: array of ref Ecmascript->Val, eval: int): ref Ecmascript->Ref; construct: fn(ex: ref Ecmascript->Exec, func: ref Ecmascript->Obj, args: array of ref Ecmascript->Val): ref Ecmascript->Obj; }; # # calls to init and mkexec do the following # math->FPcontrol(0, Math->INVAL|Math->ZDIV|Math->OVFL|Math->UNFL|Math->INEX); # Ecmascript: module { PATH: con "/dis/lib/ecmascript.dis"; # # an execution context # Exec: adt { # # well known glop # objproto: cyclic ref Obj; funcproto: cyclic ref Obj; strproto: cyclic ref Obj; numproto: cyclic ref Obj; boolproto: cyclic ref Obj; arrayproto: cyclic ref Obj; dateproto: cyclic ref Obj; regexpproto: cyclic ref Obj; errproto: cyclic ref Obj; evlerrproto: cyclic ref Obj; ranerrproto: cyclic ref Obj; referrproto: cyclic ref Obj; synerrproto: cyclic ref Obj; typerrproto: cyclic ref Obj; urierrproto: cyclic ref Obj; interrproto: cyclic ref Obj; global: cyclic ref Obj; this: cyclic ref Obj; scopechain: cyclic list of ref Obj; error: string; errval: cyclic ref Val; # # private, keep out # stack: cyclic array of ref Ref; sp: int; }; # # must be called at the dawn of time # returns error string init: fn(): string; # # initialize a new global execution context # if go is supplied, it's the global object # if not, one is made up automatically # mkexec: fn(go: ref Obj): ref Exec; # # throw a runtime error # msg ends up in ex.error, and an # "ecmascript runtime error" is raised # RUNTIME: con "ecmascript runtime error"; runtime: fn(ex: ref Exec, o: ref Obj, msg: string); # runtime errors EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, InternalError: ref Obj; # # debug flags: array of 256 indexed by char # # e print ops as they are executed # f abort on an internal error # p print parsed code # r abort on any runtime error # v print value of expression statements # debug: array of int; # # parse and runt the source string # eval: fn(ex: ref Exec, src: string): Completion; Re: type ref Arena; # the fundamental data structure Obj: adt { props: cyclic array of ref Prop; prototype: cyclic ref Obj; # some builtin properties val: cyclic ref Val; call: cyclic ref Call; construct: cyclic ref Call; class: string; host: ESHostobj; # method suite for host objects re: Re; # compiled regexp for RegExp objects }; Call: adt { params: array of string; code: cyclic ref Code; ex: cyclic ref Exec; }; # attributes ReadOnly, DontEnum, DontDelete: con 1 << iota; Prop: adt { attr: int; name: string; val: cyclic ref RefVal; }; # an extra level of indirection, because sometimes properties are aliased RefVal: adt { val: cyclic ref Val; }; # types of js values TUndef, TNull, TBool, TNum, TStr, TObj, TRegExp, NoHint: con iota; Val: adt { ty: int; num: real; str: string; obj: cyclic ref Obj; rev: ref REval; }; # regular expression REval: adt { p: string; f: string; i: int; }; # intermediate result of expression evaluation Ref: adt { isref: int; val: ref Val; base: ref Obj; name: string; # name of property within base }; # completion values of statements CNormal, CBreak, CContinue, CReturn, CThrow: con iota; Completion: adt { kind: int; val: ref Val; lab: string; }; Code: adt { ops: array of byte; # all instructions npc: int; # end of active portion of ops vars: cyclic array of ref Prop; # variables defined in the code ids: array of string; # ids used in the code strs: array of string; # string literal nums: array of real; # numerical literals fexps: cyclic array of ref Obj; # function expressions }; # # stuff for adding host objects # # ecmascript is also a host object; get: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; put: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string, val: ref Ecmascript->Val); canput: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; hasproperty: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; delete: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string); defaultval: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, tyhint: int): ref Ecmascript->Val; call: fn(ex: ref Ecmascript->Exec, func, this: ref Ecmascript->Obj, args: array of ref Ecmascript->Val, eval: int): ref Ecmascript->Ref; construct: fn(ex: ref Ecmascript->Exec, func: ref Ecmascript->Obj, args: array of ref Ecmascript->Val): ref Ecmascript->Obj; # # return the named variable from the scope chain sc # bivar: fn(ex: ref Exec, sc: list of ref Obj, s: string): ref Val; # # return the nth argument value, or undefined if too far # biarg: fn(args: array of ref Val, n: int): ref Val; # # make up a new object # most often called as mkobj(ex.objproto, "Object") # mkobj: fn(proto: ref Obj, class: string): ref Obj; # # object installation helpers # Builtin: adt { name: string; val: string; params: array of string; length: int; }; biinst: fn(o: ref Obj, bi: Builtin, proto: ref Obj, h: ESHostobj): ref Obj; biminst: fn(o: ref Obj, bis: array of Builtin, proto: ref Obj, h: ESHostobj); # # instantiate a new variable inside an object # varinstant: fn(in: ref Obj, attr: int, name: string, val: ref RefVal); # # various constructors # objval: fn(o: ref Obj): ref Val; strval: fn(s: string): ref Val; numval: fn(r: real): ref Val; valref: fn(v: ref Val): ref Ref; # # conversion routines defined in section 9 # toPrimitive: fn(ex: ref Exec, v: ref Val, ty: int): ref Val; toBoolean: fn(ex: ref Exec, v: ref Val): ref Val; toNumber: fn(ex: ref Exec, v: ref Val): real; toInteger: fn(ex: ref Exec, v: ref Val): real; toInt32: fn(ex: ref Exec, v: ref Val): int; toUint32: fn(ex: ref Exec, v: ref Val): big; toUint16: fn(ex: ref Exec, v: ref Val): int; toString: fn(ex: ref Exec, v: ref Val): string; toObject: fn(ex: ref Exec, v: ref Val): ref Obj; # # simple coercion routines to force # Boolean, String, and Number values to objects and vice versa # coerceToObj: fn(ex: ref Exec, v: ref Val): ref Val; coerceToVal: fn(v: ref Val): ref Val; # # object/value kind checkers # isstrobj: fn(o: ref Obj): int; isnumobj: fn(o: ref Obj): int; isboolobj: fn(o: ref Obj): int; isdateobj: fn(o: ref Obj): int; isregexpobj: fn(o: ref Obj): int; isarray: fn(o: ref Obj): int; isstr: fn(v: ref Val): int; isnum: fn(v: ref Val): int; isbool: fn(v: ref Val): int; isobj: fn(v: ref Val): int; # # well-known ecmascript primitive values # undefined: ref Val; true: ref Val; false: ref Val; null: ref Val; # regexp data structures refRex: type int; # used instead of ref Rex to avoid circularity Set: adt { # character class neg: int; # 0 or 1 ascii: array of int; # ascii members, bit array unicode: list of (int,int); # non-ascii char ranges subset: cyclic list of ref Set; }; Nstate: adt{ m: int; n: int; }; Rex: adt { # node in parse of regex, or state of fsm kind: int; # kind of node: char or ALT, CAT, etc left: refRex; # left descendant right: refRex; # right descendant, or next state set: ref Set; # character class pno: int; greedy: int; ns: ref Nstate; }; Arena: adt { # free store from which nodes are allocated rex: array of Rex; ptr: refRex; # next available space start: refRex; # root of parse, or start of fsm pno: int; }; };