1ESHostobj: module 2{ 3 # 4 # extensible interface for adding host objects 5 # 6 # any implementation must obey the rules of the interpreter. 7 # it is an error to return bogus values, and may cause 8 # the interpreter to crash. 9 # 10 # get/put must return/set the value of property in o 11 # 12 # canput and hasproperty return es->true or es->false 13 # 14 # defaultval must return a primitive (non-object) value. 15 # this means it can't return a String object, etc. 16 # 17 # call gets the caller's execution context in ex. 18 # the new this value is passed as an argument, 19 # but no new scopechain is allocated 20 # it returns a reference, which is typically just a value 21 # 22 # construct should make up a new object 23 # 24 get: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; 25 put: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string, val: ref Ecmascript->Val); 26 canput: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; 27 hasproperty: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; 28 delete: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string); 29 defaultval: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, tyhint: int): ref Ecmascript->Val; 30 call: fn(ex: ref Ecmascript->Exec, func, this: ref Ecmascript->Obj, args: array of ref Ecmascript->Val, eval: int): ref Ecmascript->Ref; 31 construct: fn(ex: ref Ecmascript->Exec, func: ref Ecmascript->Obj, args: array of ref Ecmascript->Val): ref Ecmascript->Obj; 32}; 33 34# 35# calls to init and mkexec do the following 36# math->FPcontrol(0, Math->INVAL|Math->ZDIV|Math->OVFL|Math->UNFL|Math->INEX); 37# 38Ecmascript: module 39{ 40 PATH: con "/dis/lib/ecmascript.dis"; 41 42 # 43 # an execution context 44 # 45 Exec: adt 46 { 47 # 48 # well known glop 49 # 50 objproto: cyclic ref Obj; 51 funcproto: cyclic ref Obj; 52 strproto: cyclic ref Obj; 53 numproto: cyclic ref Obj; 54 boolproto: cyclic ref Obj; 55 arrayproto: cyclic ref Obj; 56 dateproto: cyclic ref Obj; 57 regexpproto: cyclic ref Obj; 58 errproto: cyclic ref Obj; 59 evlerrproto: cyclic ref Obj; 60 ranerrproto: cyclic ref Obj; 61 referrproto: cyclic ref Obj; 62 synerrproto: cyclic ref Obj; 63 typerrproto: cyclic ref Obj; 64 urierrproto: cyclic ref Obj; 65 interrproto: cyclic ref Obj; 66 67 global: cyclic ref Obj; 68 this: cyclic ref Obj; 69 scopechain: cyclic list of ref Obj; 70 71 error: string; 72 errval: cyclic ref Val; 73 74 # 75 # private, keep out 76 # 77 stack: cyclic array of ref Ref; 78 sp: int; 79 }; 80 81 # 82 # must be called at the dawn of time 83 # returns error string 84 init: fn(): string; 85 86 # 87 # initialize a new global execution context 88 # if go is supplied, it's the global object 89 # if not, one is made up automatically 90 # 91 mkexec: fn(go: ref Obj): ref Exec; 92 93 # 94 # throw a runtime error 95 # msg ends up in ex.error, and an 96 # "ecmascript runtime error" is raised 97 # 98 RUNTIME: con "ecmascript runtime error"; 99 runtime: fn(ex: ref Exec, o: ref Obj, msg: string); 100 101 # runtime errors 102 EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, InternalError: ref Obj; 103 104 # 105 # debug flags: array of 256 indexed by char 106 # 107 # e print ops as they are executed 108 # f abort on an internal error 109 # p print parsed code 110 # r abort on any runtime error 111 # v print value of expression statements 112 # 113 debug: array of int; 114 115 # 116 # parse and runt the source string 117 # 118 eval: fn(ex: ref Exec, src: string): Completion; 119 120 Re: type ref Arena; 121 122 # the fundamental data structure 123 Obj: adt 124 { 125 props: cyclic array of ref Prop; 126 prototype: cyclic ref Obj; # some builtin properties 127 val: cyclic ref Val; 128 call: cyclic ref Call; 129 construct: cyclic ref Call; 130 class: string; 131 host: ESHostobj; # method suite for host objects 132 re: Re; # compiled regexp for RegExp objects 133 }; 134 135 Call: adt 136 { 137 params: array of string; 138 code: cyclic ref Code; 139 ex: cyclic ref Exec; 140 }; 141 142 # attributes 143 ReadOnly, DontEnum, DontDelete: con 1 << iota; 144 Prop: adt 145 { 146 attr: int; 147 name: string; 148 val: cyclic ref RefVal; 149 }; 150 151 # an extra level of indirection, because sometimes properties are aliased 152 RefVal: adt 153 { 154 val: cyclic ref Val; 155 }; 156 157 # types of js values 158 TUndef, TNull, TBool, TNum, TStr, TObj, TRegExp, NoHint: con iota; 159 Val: adt 160 { 161 ty: int; 162 num: real; 163 str: string; 164 obj: cyclic ref Obj; 165 rev: ref REval; 166 }; 167 168 # regular expression 169 REval: adt 170 { 171 p: string; 172 f: string; 173 i: int; 174 }; 175 176 # intermediate result of expression evaluation 177 Ref: adt 178 { 179 isref: int; 180 val: ref Val; 181 base: ref Obj; 182 name: string; # name of property within base 183 }; 184 185 # completion values of statements 186 CNormal, CBreak, CContinue, CReturn, CThrow: con iota; 187 Completion: adt 188 { 189 kind: int; 190 val: ref Val; 191 lab: string; 192 }; 193 194 Code: adt 195 { 196 ops: array of byte; # all instructions 197 npc: int; # end of active portion of ops 198 vars: cyclic array of ref Prop; # variables defined in the code 199 ids: array of string; # ids used in the code 200 strs: array of string; # string literal 201 nums: array of real; # numerical literals 202 fexps: cyclic array of ref Obj; # function expressions 203 }; 204 205 # 206 # stuff for adding host objects 207 # 208 # ecmascript is also a host object; 209 get: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; 210 put: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string, val: ref Ecmascript->Val); 211 canput: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; 212 hasproperty: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string): ref Ecmascript->Val; 213 delete: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, property: string); 214 defaultval: fn(ex: ref Ecmascript->Exec, o: ref Ecmascript->Obj, tyhint: int): ref Ecmascript->Val; 215 call: fn(ex: ref Ecmascript->Exec, func, this: ref Ecmascript->Obj, args: array of ref Ecmascript->Val, eval: int): ref Ecmascript->Ref; 216 construct: fn(ex: ref Ecmascript->Exec, func: ref Ecmascript->Obj, args: array of ref Ecmascript->Val): ref Ecmascript->Obj; 217 218 # 219 # return the named variable from the scope chain sc 220 # 221 bivar: fn(ex: ref Exec, sc: list of ref Obj, s: string): ref Val; 222 223 # 224 # return the nth argument value, or undefined if too far 225 # 226 biarg: fn(args: array of ref Val, n: int): ref Val; 227 228 # 229 # make up a new object 230 # most often called as mkobj(ex.objproto, "Object") 231 # 232 mkobj: fn(proto: ref Obj, class: string): ref Obj; 233 234 # 235 # object installation helpers 236 # 237 Builtin: adt 238 { 239 name: string; 240 val: string; 241 params: array of string; 242 length: int; 243 }; 244 biinst: fn(o: ref Obj, bi: Builtin, proto: ref Obj, h: ESHostobj): ref Obj; 245 biminst: fn(o: ref Obj, bis: array of Builtin, proto: ref Obj, h: ESHostobj); 246 247 # 248 # instantiate a new variable inside an object 249 # 250 varinstant: fn(in: ref Obj, attr: int, name: string, val: ref RefVal); 251 252 # 253 # various constructors 254 # 255 objval: fn(o: ref Obj): ref Val; 256 strval: fn(s: string): ref Val; 257 numval: fn(r: real): ref Val; 258 valref: fn(v: ref Val): ref Ref; 259 260 # 261 # conversion routines defined in section 9 262 # 263 toPrimitive: fn(ex: ref Exec, v: ref Val, ty: int): ref Val; 264 toBoolean: fn(ex: ref Exec, v: ref Val): ref Val; 265 toNumber: fn(ex: ref Exec, v: ref Val): real; 266 toInteger: fn(ex: ref Exec, v: ref Val): real; 267 toInt32: fn(ex: ref Exec, v: ref Val): int; 268 toUint32: fn(ex: ref Exec, v: ref Val): big; 269 toUint16: fn(ex: ref Exec, v: ref Val): int; 270 toString: fn(ex: ref Exec, v: ref Val): string; 271 toObject: fn(ex: ref Exec, v: ref Val): ref Obj; 272 273 # 274 # simple coercion routines to force 275 # Boolean, String, and Number values to objects and vice versa 276 # 277 coerceToObj: fn(ex: ref Exec, v: ref Val): ref Val; 278 coerceToVal: fn(v: ref Val): ref Val; 279 280 # 281 # object/value kind checkers 282 # 283 isstrobj: fn(o: ref Obj): int; 284 isnumobj: fn(o: ref Obj): int; 285 isboolobj: fn(o: ref Obj): int; 286 isdateobj: fn(o: ref Obj): int; 287 isregexpobj: fn(o: ref Obj): int; 288 isarray: fn(o: ref Obj): int; 289 isstr: fn(v: ref Val): int; 290 isnum: fn(v: ref Val): int; 291 isbool: fn(v: ref Val): int; 292 isobj: fn(v: ref Val): int; 293 294 # 295 # well-known ecmascript primitive values 296 # 297 undefined: ref Val; 298 true: ref Val; 299 false: ref Val; 300 null: ref Val; 301 302 # regexp data structures 303 304 refRex: type int; # used instead of ref Rex to avoid circularity 305 306 Set: adt { # character class 307 neg: int; # 0 or 1 308 ascii: array of int; # ascii members, bit array 309 unicode: list of (int,int); # non-ascii char ranges 310 subset: cyclic list of ref Set; 311 }; 312 313 Nstate: adt{ 314 m: int; 315 n: int; 316 }; 317 318 Rex: adt { # node in parse of regex, or state of fsm 319 kind: int; # kind of node: char or ALT, CAT, etc 320 left: refRex; # left descendant 321 right: refRex; # right descendant, or next state 322 set: ref Set; # character class 323 pno: int; 324 greedy: int; 325 ns: ref Nstate; 326 }; 327 328 Arena: adt { # free store from which nodes are allocated 329 rex: array of Rex; 330 ptr: refRex; # next available space 331 start: refRex; # root of parse, or start of fsm 332 pno: int; 333 }; 334}; 335