1 /* -*- mode: java; tab-width: 4; insert-tabs-mode: nil; indent-tabs-mode: nil -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is [Open Source Virtual Machine.].
17 * The Initial Developer of the Original Code is
18 * Adobe System Incorporated.
19 * Portions created by the Initial Developer are Copyright (C) 2004-2006
20 * the Initial Developer. All Rights Reserved.
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 use default namespace Ast,
42 interface Serializable {
43 function serialize(s);
47 public function toString()
48 (new Serializer(true)).serialize(this);
53 type IDENT = Token::Tok; // hm, how does this serialize??
55 class Head extends ASTNode implements Serializable {
56 const fixtures: [...Fixture];
57 const exprs: [...Expr];
58 const cache = null; // used by the definer, for the moment
59 function Head (fixtures,exprs)
64 s.sClass(this, "Head", "fixtures", "exprs");
67 class Fixture extends ASTNode implements Serializable {
68 const name: FixtureName;
69 const data: FixtureData;
70 function Fixture(name, data) : name=name, data=data {}
73 s.sClass(this, "Fixture", "name", "data");
76 interface FixtureName {
79 // FIXME: conflating "temps" and "positional parameters" seems wrong
80 // and is an unnecessary Tamarin dependency. The parser uses TempName
81 // for "positional parameter" but will want to start using something
82 // for true unforgeable temporaries.
84 class TempName extends ASTNode implements FixtureName, Serializable {
86 function TempName (index) : index=index {}
89 s.sClass(this, "TempName", "index");
92 // FIXME: does this serve any purpose at all? Strikes me as pure
93 // bureaucracy. (It does allow FixtureName to be attached, but it
94 // seems that the real problem -- see comment above -- is that naming
95 // in general is not all that coherent atm.
97 class PropName extends ASTNode implements FixtureName, Serializable {
99 function PropName(name) : name=name {}
101 function serialize(s)
102 s.sClass(this, "PropName", "name");
105 class InitBinding extends ASTNode implements Serializable {
106 const name: FixtureName;
108 function InitBinding(name, expr) : name=name, expr=expr {}
110 function serialize(s)
111 s.sClass(this, "InitBinding", "name", "expr");
114 class Name extends ASTNode implements Serializable {
117 function Name(ns, id) : ns=ns, id=id {}
119 function serialize(s)
120 s.sClass(this, "Name", "ns", "id");
123 // Must be qualified everywhere it's used as 'Ast::Namespace' because
124 // Tamarin does not (yet) have prioritized name lookup.
126 interface Namespace {
129 function nsEquals(ns1, ns2) {
132 if (ns1.name != ns2.name)
135 case (x: UnforgeableNamespace) { return ns2 is UnforgeableNamespace; }
136 case (x: ForgeableNamespace) { return ns2 is UnforgeableNamespace; }
137 case (x: PrivateNamespace) { return ns2 is PrivateNamespace; }
138 case (x: ProtectedNamespace) { return ns2 is ProtectedNamespace; }
139 case (x: PublicNamespace) { return ns2 is PublicNamespace; }
140 case (x: InternalNamespace) { return ns2 is InternalNamespace; }
141 case (x: *) { return ns1.hash() == ns2.hash(); }
145 class PrivateNamespace extends ASTNode implements Ast::Namespace, Serializable {
147 function PrivateNamespace (name)
149 function hash () { return "private " + name; }
151 function serialize(s)
152 s.sClass(this, "PrivateNamespace", "name");
155 class ProtectedNamespace extends ASTNode implements Ast::Namespace, Serializable {
157 function ProtectedNamespace (name)
159 function hash () { return "protected " + name; }
161 function serialize(s)
162 s.sClass(this, "ProtectedNamespace", "name");
165 class PublicNamespace extends ASTNode implements Ast::Namespace, Serializable {
167 function PublicNamespace (name)
169 function hash () { return "public " + name; }
171 function serialize(s)
172 s.sClass(this, "PublicNamespace", "name");
175 class InternalNamespace extends ASTNode implements Ast::Namespace, Serializable {
177 function InternalNamespace (name)
179 function hash () { return "internal " + name; }
181 function serialize(s)
182 s.sClass(this, "InternalNamespace", "name");
185 class ForgeableNamespace extends ASTNode implements Ast::Namespace, Serializable {
187 function ForgeableNamespace (name)
189 function hash () { return "forgeable " + name; }
191 function serialize(s)
192 s.sClass(this, "ForgeableNamespace", "name");
195 class UnforgeableNamespace extends ASTNode implements Ast::Namespace, Serializable {
197 function UnforgeableNamespace (name)
199 function hash () { return "unforgeable " + name; }
201 function serialize(s)
202 s.sClass(this, "UnforgeableNamespace", "name");
205 internal var nshash = 0; // Used as an object ID for namespace nodes in the back end
207 // The correctness of optimizations in the back-end depends on
208 // NamespaceSet and NamespaceSetList being functional data structures.
210 final class NamespaceSet extends ASTNode implements Serializable {
212 const link: NamespaceSet;
213 const hash = nshash++;
214 function NamespaceSet(ns, link) : ns=ns, link=link {}
216 function serialize(s)
217 s.sClass(this, "NamespaceSet", "ns", "link");
220 final class NamespaceSetList extends ASTNode implements Serializable {
221 const nsset: NamespaceSet;
222 const link : NamespaceSetList;
223 const hash = nshash++;
224 function NamespaceSetList(nsset, link) : nsset=nsset, link=link {}
226 function serialize(s)
227 s.sClass(this, "NamespaceSetList", "nsset", "link");
230 new NamespaceSetList(null, this);
232 function pushNamespace(ns)
233 new NamespaceSetList(new NamespaceSet(ns, nsset), this.link);
236 const publicNS = new Ast::PublicNamespace(Token::sym_EMPTY);
237 const publicNSSL = new Ast::NamespaceSetList(new Ast::NamespaceSet(publicNS, null), null);
239 // Binary type operators
247 // Binary arithmetic and logical operators
255 const remainderOp = 4;
256 const leftShiftOp = 5;
257 const rightShiftOp = 6;
258 const rightShiftUnsignedOp = 7;
259 const bitwiseAndOp = 8;
260 const bitwiseOrOp = 9;
261 const bitwiseXorOp = 10;
262 const logicalAndOp = 11;
263 const logicalOrOp = 12;
264 const instanceOfOp = 13;
267 const notEqualOp = 16;
268 const strictEqualOp = 17;
269 const strictNotEqualOp = 18;
271 const lessOrEqualOp = 20;
272 const greaterOp = 21;
273 const greaterOrEqualOp = 22;
276 // Assignment operators
281 const assignPlusOp = 1;
282 const assignMinusOp = 2;
283 const assignTimesOp = 3;
284 const assignDivideOp = 4;
285 const assignRemainderOp = 5;
286 const assignLeftShiftOp = 6;
287 const assignRightShiftOp = 7;
288 const assignRightShiftUnsignedOp = 8;
289 const assignBitwiseAndOp = 9;
290 const assignBitwiseOrOp = 10;
291 const assignBitwiseXorOp = 11;
292 const assignLogicalAndOp = 12;
293 const assignLogicalOrOp = 13;
295 // Unary arithmetic and logical operators
304 const postIncrOp = 5;
305 const postDecrOp = 6;
306 const unaryPlusOp = 7;
307 const unaryMinusOp = 8;
308 const bitwiseNotOp = 9;
309 const logicalNotOp = 10;
313 // The strictFlag is set on ops that generated in strict mode.
315 const strictFlag = 64;
316 const strictMask = strictFlag-1;
318 class Expr extends ASTNode {
320 function Expr(pos=0) : pos=pos {}
323 class TernaryExpr extends Expr implements Serializable {
327 function TernaryExpr (e1,e2,e3) : e1=e1, e2=e2, e3=e3 {}
329 function serialize(s)
330 s.sClass(this, "TernaryExpr", "e1", "e2", "e3");
333 class BinaryExpr extends Expr implements Serializable {
337 function BinaryExpr (op,e1,e2) : op=op, e1=e1, e2=e2 {}
339 function serialize(s)
340 s.sClass(this, "BinaryExpr", "op", "e1", "e2");
343 class BinaryTypeExpr extends Expr implements Serializable {
347 function BinaryTypeExpr (op,e1,e2) : op=op, e1=e1, e2=e2 {}
349 function serialize(s)
350 s.sClass(this, "BinaryTypeExpr", "op", "e1", "e2");
353 class UnaryExpr extends Expr implements Serializable {
356 function UnaryExpr (op,e1) : op=op, e1=e1 {}
358 function serialize(s)
359 s.sClass(this, "UnaryExpr", "op", "e1");
364 class TypeOpExpr extends Expr implements Serializable {
366 function TypeOpExpr (ex) : ex=ex {}
368 function serialize(s)
369 s.sClass(this, "TypeOpExpr", "ex");
372 class ThisExpr extends Expr implements Serializable {
373 const strict: Boolean;
374 function ThisExpr(strict) : strict=strict {}
376 function serialize(s)
377 s.sClass(this, "ThisExpr", "strict");
380 class ThisGeneratorExpr extends Expr implements Serializable {
381 function serialize(s)
382 s.sClass(this, "ThisGeneratorExpr");
385 class ThisFunctionExpr extends Expr implements Serializable {
386 function serialize(s)
387 s.sClass(this, "ThisFunctionExpr");
391 class YieldExpr extends Expr implements Serializable {
393 function YieldExpr (ex=null) : ex=ex {}
395 function serialize(s)
396 s.sClass(this, "YieldExpr", "ex");
400 class SuperExpr extends Expr implements Serializable {
402 function SuperExpr (ex=null) : ex=ex {}
404 function serialize(s)
405 s.sClass(this, "SuperExpr", "ex");
408 class CallExpr extends Expr implements Serializable {
410 const args : [...Expr];
411 const spread: ? Expr;
412 const strict: Boolean;
413 function CallExpr (expr,args,spread,pos=0,strict=false)
420 function serialize(s)
421 s.sClass(this, "CallExpr", "expr", "args", "spread", "pos", "strict");
424 class ApplyTypeExpr extends Expr implements Serializable {
426 const args : [...TypeExpr];
427 function ApplyTypeExpr (expr,args)
431 function serialize(s)
432 s.sClass(this, "ApplyTypeExpr", "expr", "args");
435 class LetExpr extends Expr implements Serializable {
438 function LetExpr (head,expr)
442 function serialize(s)
443 s.sClass(this, "LetExpr", "head", "expr");
446 class DynamicOverrideExpr extends Expr implements Serializable {
447 const names: [...IdentExpr];
448 const exprs: [...Expr];
450 function DynamicOverrideExpr (names, exprs, body)
455 function serialize(s)
456 s.sClass(this, "DynamicOverrideExpr", "names", "exprs", "body");
459 class NewExpr extends Expr implements Serializable {
461 const args : [...Expr];
462 const spread: ? Expr;
463 function NewExpr (expr,args,spread)
468 function serialize(s)
469 s.sClass(this, "NewExpr", "expr", "args", "spread");
472 class ObjectRef extends Expr implements Serializable {
474 const ident : (IdentExpr | ComputedName);
475 function ObjectRef (base,ident,pos=0)
480 function serialize(s)
481 s.sClass(this, "ObjectRef", "base", "ident", "pos");
484 // This is used to encode obj[E] because that whole expression is
485 // encoded as an ObjectRef; the "ident" in ObjectRef (the 'E' above)
486 // turns out to be a ComputedName. Note that E cannot be a slice
487 // expression; the pattern obj[E1:E2:E3] is translated into a call
490 class ComputedName extends Expr implements Serializable {
492 function ComputedName (expr)
495 function serialize(s)
496 s.sClass(this, "ComputedName", "expr");
500 class SetExpr extends Expr implements Serializable {
504 function SetExpr (op,le,re,pos=0)
510 function serialize(s)
511 s.sClass(this, "SetExpr", "op", "le", "re");
514 class EvalScopeInitExpr extends Expr implements Serializable {
517 function EvalScopeInitExpr(index, how)
522 function serialize(s)
523 s.sClass(this, "EvalScopeInitExpr", "index", "how");
526 interface Comprehension {
529 class ComprehendIf extends Expr implements Comprehension, Serializable {
530 const condition: Expr;
531 const subclause: ? Expr;
532 function ComprehendIf(condition, subclause)
533 : condition=condition
534 , subclause=subclause {}
536 function serialize(s)
537 s.sClass(this, "ComprehendIf", "condition", "subclause");
540 class ComprehendLet extends Expr implements Comprehension, Serializable {
542 const subclause: ? Expr;
543 function ComprehendLet(head, subclause)
545 , subclause=subclause {}
547 function serialize(s)
548 s.sClass(this, "ComprehendLet", "head", "subclause");
551 class ComprehendFor extends Expr implements Comprehension, Serializable {
552 const is_each: Boolean;
554 const iterator: Expr;
555 const subclause: ? Expr;
556 function ComprehendFor(is_each, head, iterator, subclause)
560 , subclause=subclause {}
562 function serialize(s)
563 s.sClass(this, "ComprehendFor", "is_each", "head", "iterator", "subclause");
568 // Couldn't resolve to any scope/reg
569 class NoBind implements Bind {
572 const nobind = new NoBind;
574 class RegBind implements Bind {
577 function RegBind(reg, type_index)
579 , type_index = type_index { }
582 class SlotBind implements Bind {
583 const slot; // slot id
584 const scope; // Register the scope is in. Could scope ever not be in a register?
585 function SlotBind(slot, scope)
590 // FIXME: better as an ENUM, but then that needs to be serializable.
592 type INIT_TARGET = int;
596 const prototypeInit = 2;
597 const instanceInit = 3;
599 class InitExpr extends Expr implements Serializable {
600 const target : INIT_TARGET;
601 const head : Head; // for desugaring temporaries
602 const inits : [...InitBinding];
603 function InitExpr (target, head, inits)
608 function serialize(s)
609 s.sClass(this, "InitExpr", "target", "head", "inits");
612 class GetTemp extends Expr implements Serializable {
617 function serialize(s)
618 s.sClass(this, "GetTemp", "n");
621 class GetParam extends Expr implements Serializable {
623 function GetParam (n)
626 function serialize(s)
627 s.sClass(this, "GetParam", "n");
630 class GetCogenTemp extends Expr implements Serializable {
631 const n; // set by the code generator
632 function GetCogenTemp() {}
634 function serialize(s)
635 s.sClass(this, "GetCogenTemp");
638 interface IdentExpr {
641 // Values in nss are unresolved expressions until definition time, but
642 // the parser also places literal namespace values in the list when it
645 class Identifier extends Expr implements IdentExpr, Serializable {
647 const nss: [...(Ast::Namespace | Expr)];
649 function Identifier (ident,nss,pos=0)
652 , binding = undefined
655 function serialize(s)
656 s.sClass(this, "Identifier", "ident", "nss");
659 class QualifiedIdentifier extends Expr implements IdentExpr, Serializable {
660 const qual : (Ast::Namespace | Expr);
662 function QualifiedIdentifier (qual,ident,pos=0)
667 function serialize(s)
668 s.sClass(this, "QualifiedIdentifier", "qual", "ident");
671 interface LiteralExpr {
674 class LiteralNull extends Expr implements LiteralExpr, Serializable {
675 function LiteralNull(pos=0)
678 function serialize(s)
679 s.sClass(this, "LiteralNull");
682 class LiteralUndefined extends Expr implements LiteralExpr, Serializable {
683 function LiteralUndefined(pos=0)
686 function serialize(s)
687 s.sClass(this, "LiteralUndefined");
690 class LiteralDouble extends Expr implements LiteralExpr, Serializable {
691 const doubleValue : Number;
692 function LiteralDouble (doubleValue, pos=0)
693 : doubleValue=doubleValue
696 function serialize(s)
697 s.sClass(this, "LiteralDouble", "doubleValue");
700 class LiteralDecimal extends Expr implements LiteralExpr, Serializable {
701 const decimalValue : decimal;
702 function LiteralDecimal (decimalValue, pos=0)
703 : decimalValue = decimalValue
706 function serialize(s)
707 s.sClass(this, "LiteralDouble", "decimalValue");
710 class LiteralInt extends Expr implements LiteralExpr, Serializable {
711 const intValue : int;
712 function LiteralInt(intValue, pos=0)
716 function serialize(s)
717 s.sClass(this, "LiteralInt", "intValue");
720 class LiteralUInt extends Expr implements LiteralExpr, Serializable {
721 const uintValue : uint;
722 function LiteralUInt(uintValue, pos=0)
723 : uintValue=uintValue
726 function serialize(s)
727 s.sClass(this, "LiteralUInt", "uintValue");
730 class LiteralBoolean extends Expr implements LiteralExpr, Serializable {
731 const booleanValue : Boolean;
732 function LiteralBoolean(booleanValue, pos=0)
733 : booleanValue=booleanValue
736 function serialize(s)
737 s.sClass(this, "LiteralBoolean", "booleanValue");
740 class LiteralString extends Expr implements LiteralExpr, Serializable {
741 const strValue : Token::Tok;
742 function LiteralString (strValue, pos=0)
743 : strValue = strValue
746 function serialize(s)
747 s.sClass(this, "LiteralString", "strValue");
750 class LiteralArray extends Expr implements LiteralExpr, Serializable {
751 const exprs : [...Expr];
752 const spread : ? Expr;
754 function LiteralArray (exprs, spread, ty, pos=0)
760 function serialize(s)
761 s.sClass(this, "LiteralArray", "exprs", "ty");
764 class LiteralComprehension extends Expr implements LiteralExpr, Serializable {
766 const comprehension : Comprehension;
768 function LiteralComprehension (expr, comprehension, ty, pos=0)
770 , comprehension = comprehension
774 function serialize(s)
775 s.sClass(this, "LiteralComprehension", "expr", "comprehension", "ty");
778 class LiteralNamespace extends Expr implements LiteralExpr, Serializable {
779 const namespaceValue : Ast::Namespace;
780 function LiteralNamespace (namespaceValue, pos=0)
781 : namespaceValue = namespaceValue
784 function serialize(s)
785 s.sClass(this, "LiteralNamespace", "namespaceValue");
788 class LiteralObject extends Expr implements LiteralExpr, Serializable {
789 const fields : [...LiteralField];
791 function LiteralObject (fields, ty, pos=0)
796 function serialize(s)
797 s.sClass(this, "LiteralObject", "fields", "ty");
800 class LiteralField extends ASTNode implements Serializable {
801 const kind: VAR_DEFN_TAG;
802 const ident: IdentExpr;
804 function LiteralField (kind,ident,expr)
809 function serialize(s)
810 s.sClass(this, "LiteralField", "kind", "ident", "expr");
813 class ProtoField extends ASTNode implements Serializable {
815 function ProtoField(expr) : expr=expr {}
817 function serialize(s)
818 s.sClass(this, "ProtoField", "expr");
821 class VirtualField extends ASTNode implements Serializable {
822 const tag : VAR_DEFN_TAG;
823 const name : IdentExpr;
824 const kind : FUNC_NAME_KIND;
826 function VirtualField(tag, name, kind, func)
832 function serialize(s)
833 s.sClass(this, "VirtualField", "tag", "name", "kind", "func");
837 class LiteralFunction extends Expr implements LiteralExpr, Serializable {
839 function LiteralFunction (func, pos=0)
843 function serialize(s)
844 s.sClass(this, "LiteralFunction", "func");
847 class LiteralRegExp extends Expr implements LiteralExpr, Serializable {
848 const src : Token::Tok;
849 function LiteralRegExp(src, pos=0)
853 function serialize(s)
854 s.sClass(this, "LiteralRegExp", "src");
857 type VAR_DEFN_TAG = int;
859 const noTag = 0; // dynamic property
860 const constTag = 1; // 'const' fixture or parameter
861 const varTag = 2; // 'var' fixture or parameter
864 class VariableDefn extends ASTNode implements Serializable {
866 const isStatic: Boolean;
867 const isPrototype: Boolean;
868 const kind: VAR_DEFN_TAG;
869 const bindings: BINDING_INITS;
870 function VariableDefn (ns,isStatic,isPrototype,kind,bindings)
872 , isStatic = isStatic
873 , isPrototype = isPrototype
875 , bindings = bindings {}
877 function serialize(s)
878 s.sClass(this, "VariableDefn", "ns", "isStatic", "isPrototype", "kind", "bindings");
882 class Cls extends ASTNode implements Serializable {
884 const typeParams: [...TypeExpr];
885 const nonnullable: Boolean;
886 const baseName: IdentExpr;
887 const interfaceNames: [...IdentExpr];
889 const constructor : Ctor;
890 const classHead: Head;
891 const instanceHead: Head;
892 const classType: ObjectType;
893 const instanceType: InstanceType;
894 const classBody: [...Stmt];
897 function Cls (name,typeParams,nonnullable,baseName,interfaceNames,protectedns,
898 constructor,classHead,instanceHead,classType,instanceType,classBody,
901 , typeParams = typeParams
902 , nonnullable = nonnullable
903 , baseName = baseName
904 , interfaceNames = interfaceNames
905 , protectedns = protectedns
906 , constructor = constructor
907 , classHead = classHead
908 , instanceHead = instanceHead
909 , classType = classType
910 , instanceType = instanceType
911 , classBody = classBody
912 , isDynamic = isDynamic
916 function serialize(s)
917 s.sClass(this, "Cls",
918 "name", "typeParams", "nonnullable", "baseName", "interfaceNames", "protectedns",
919 "constructor", "classHead", "instanceHead", "classType", "instanceType", "classBody",
920 "isDynamic", "isFinal");
923 class Interface extends ASTNode implements Serializable {
925 const typeParams: [...TypeExpr];
926 const interfaceNames: [...IdentExpr];
927 const instanceHead: Head;
928 function Interface (name,typeParams,interfaceNames,instanceHead)
930 , typeParams = typeParams
931 , interfaceNames = interfaceNames
932 , instanceHead = instanceHead
935 function serialize(s)
936 s.sClass(this, "Interface", "typeParams", "name", "interfaceNames", "instanceHead");
941 // FIXME: 'TAG' is better here, see above uses.
942 type FUNC_NAME_KIND = int;
944 const ordinaryFunction = 0;
945 const getterFunction = 1;
946 const setterFunction = 2;
947 const staticInitFunction = 3;
949 class FuncName extends ASTNode implements Serializable {
950 const kind: FUNC_NAME_KIND;
952 function FuncName(kind, ident) : kind=kind, ident=ident {}
954 function serialize(s)
955 s.sClass(this, "FuncName", "kind", "ident");
958 class FuncAttr extends ASTNode implements Serializable {
959 /* Outer function, or null if the function is at the global
960 level (including for class methods). */
961 const parent: FuncAttr;
963 /* Nested functions and function expressions, empty for leaf functions */
966 /* True iff identifier "arguments" lexically referenced in function body.
967 Note that the parameter list is excluded. */
968 var uses_arguments = false;
970 /* True iff identifier expression "eval" is lexically referenced
971 in the function body as the operator in a call expression. */
972 var uses_eval = false;
974 /* True iff ...<id> appears in the parameter list. */
975 var uses_rest = false;
977 /* True iff the body has a "with" statement */
978 var uses_with = false;
980 /* True iff the body has a "try" statement with a "catch" clause */
981 var uses_catch = false;
983 /* True iff the body has a "try" statement with a "finally" clause */
984 var uses_finally = false;
986 /* True iff the body has a "yield" statement or expression */
987 var uses_yield = false;
989 /* True iff this is a constructor whose body or settings has an
990 explicit "super" call */
991 var uses_super = false;
993 /* True iff this function is native */
994 var is_native = false;
996 /* True iff the function must capture its statement result value and return it if
997 control falls off the end */
998 var capture_result = false;
1000 /* Synthesized: true iff activation object must be reified for any reason */
1001 var reify_activation = false;
1003 function FuncAttr(...rest) {
1004 if (rest.length == 1) {
1005 this.parent = rest[0];
1009 // Unserialization. An ad hoc pass over the AST will (hopefully) take
1010 // care of patching up parent/children.
1011 [uses_arguments, uses_eval, uses_rest, uses_with, uses_catch,
1012 uses_finally, uses_yield, uses_super, is_native, capture_result,
1013 reify_activation] = rest;
1017 function serialize(s)
1018 s.sClass(this, "FuncAttr", "uses_arguments", "uses_eval", "uses_rest", "uses_with",
1019 "uses_catch", "uses_finally", "uses_yield", "uses_super", "is_native",
1020 "capture_result", "reify_activation");
1023 class Func extends ASTNode implements Serializable {
1024 const name; //: FUNC_NAME;
1025 const body: [...Stmt];
1027 const numparams: int;
1029 const defaults: [...Expr];
1031 const attr: FuncAttr;
1032 const strict: Boolean;
1035 function Func (name,body,params,numparams,vars,defaults,ty,attr,strict,pos=0,filename=null)
1039 , numparams = numparams
1041 , defaults = defaults
1046 , filename = filename {}
1048 function serialize(s)
1049 s.sClass(this, "Func", "name", "body", "params", "numparams", "vars", "defaults", "ty", "attr", "strict", "pos", "filename");
1052 class Ctor extends ASTNode implements Serializable {
1053 const settings : [...Expr];
1054 const superArgs : ? [...Expr]; // Will be null if there is no 'super' call in the settings
1055 const superSpread: ? Expr
1057 function Ctor (settings,superArgs,superSpread,func)
1058 : settings = settings
1059 , superArgs = superArgs
1060 , superSpread = superSpread
1063 function serialize(s)
1064 s.sClass(this, "Ctor", "settings", "superArgs", "superSpread", "func");
1067 interface BindingIdent {
1070 class TempIdent extends ASTNode implements BindingIdent, Serializable {
1072 function TempIdent (index)
1075 function serialize(s)
1076 s.sClass(this, "TempIdent", "index");
1079 class ParamIdent extends ASTNode implements BindingIdent, Serializable {
1081 function ParamIdent (index)
1084 function serialize(s)
1085 s.sClass(this, "ParamIdent", "index");
1088 class PropIdent extends ASTNode implements BindingIdent, Serializable {
1089 const ident : IDENT;
1090 function PropIdent (ident)
1093 function serialize(s)
1094 s.sClass(this, "PropIdent", "ident");
1097 interface FixtureData {
1100 class NamespaceFixture extends ASTNode implements FixtureData, Serializable {
1101 const ns : Ast::Namespace;
1102 function NamespaceFixture (ns)
1105 function serialize(s)
1106 s.sClass(this, "NamespaceFixture", "ns");
1109 internal class FixtureFwd extends ASTNode implements FixtureData {
1110 const params : [...IDENT];
1111 const nonnullable: Boolean;
1112 function FixtureFwd (params, nonnullable)
1114 , nonnullable=nonnullable {}
1117 class ClassFixtureFwd extends FixtureFwd implements Serializable {
1118 function ClassFixtureFwd (params, nonnullable) : super(params, nonnullable) {}
1120 function serialize(s)
1121 s.sClass(this, "ClassFixtureFwd", "params", "nonnullable");
1124 class ClassFixture extends ASTNode implements FixtureData, Serializable {
1126 function ClassFixture (cls)
1129 function serialize(s)
1130 s.sClass(this, "ClassFixture", "cls");
1133 class InterfaceFixtureFwd extends FixtureFwd implements Serializable {
1134 function InterfaceFixtureFwd (params) : super(params, false) {}
1136 function serialize(s)
1137 s.sClass(this, "InterfaceFixtureFwd", "params");
1140 class InterfaceFixture extends ASTNode implements FixtureData, Serializable {
1141 const iface : Interface;
1142 function InterfaceFixture (iface)
1145 function serialize(s)
1146 s.sClass(this, "InterfaceFixture", "iface");
1150 class TypeVarFixture extends ASTNode implements FixtureData, Serializable {
1151 function serialize(s)
1152 s.sClass(this, "TypeVarFixture");
1156 class TypeFixtureFwd extends FixtureFwd implements Serializable {
1157 function TypeFixtureFwd (params, nonnullable) : super(params, nonnullable) {}
1159 function serialize(s)
1160 s.sClass(this, "TypeFixtureFwd", "params", "nonnullable");
1163 class TypeFixture extends ASTNode implements FixtureData, Serializable {
1164 const params : [...IDENT];
1165 const nonnullable: Boolean;
1166 const ty : TypeExpr;
1167 function TypeFixture (params, nonnullable, ty)
1169 , nonnullable=nonnullable
1172 function serialize(s)
1173 s.sClass(this, "TypeFixture", "params", "nonnullable", "ty");
1176 class MethodFixture extends ASTNode implements FixtureData, Serializable {
1178 const ty : TypeExpr;
1179 const isReadOnly : Boolean;
1180 const isOverride : Boolean;
1181 const isFinal : Boolean;
1182 function MethodFixture(func, ty, isReadOnly, isOverride, isFinal)
1185 , isReadOnly = isReadOnly
1186 , isOverride = isOverride
1187 , isFinal = isFinal { }
1189 function serialize(s)
1190 s.sClass(this, "MethodFixture", "func", "ty", "isReadOnly", "isOverride", "isFinal");
1193 class ValFixture extends ASTNode implements FixtureData, Serializable {
1194 const ty : TypeExpr;
1195 const isReadOnly : Boolean;
1196 function ValFixture(ty, isReadOnly)
1198 , isReadOnly=isReadOnly {}
1200 function serialize(s)
1201 s.sClass(this, "ValFixture", "ty", "isReadOnly");
1204 class VirtualValFixture extends ASTNode implements FixtureData, Serializable {
1205 const ty : TypeExpr;
1206 const getter : ? Func;
1207 const setter : ? Func;
1209 function VirtualValFixture(ty, getter, setter)
1214 function serialize(s)
1215 s.sClass(this, "VirtualValFixture", "ty", "getter", "setter");
1218 interface TypeExpr {
1221 type SPECIAL_TYPE_KIND = int;
1223 class SpecialType extends ASTNode implements TypeExpr, Serializable {
1224 const kind : SPECIAL_TYPE_KIND;
1225 function SpecialType(kind) : kind=kind {}
1227 function serialize(s)
1228 s.sConstant("Ast::specialTypes[" + kind + "]");
1231 const specialTypes = [new SpecialType(0),
1234 new SpecialType(3)];
1236 const [anyType, nullType, undefinedType, voidType] = specialTypes;
1238 // These may not be required any more, serialization and
1239 // deserialization preserves identity of the special type objects.
1241 function isAnyType(t:TypeExpr): Boolean
1242 t is SpecialType && t.kind == 0;
1244 function isNullType(t:TypeExpr): Boolean
1245 t is SpecialType && t.kind == 1;
1247 function isUndefinedType(t:TypeExpr): Boolean
1248 t is SpecialType && t.kind == 2;
1250 function isVoidType(t:TypeExpr): Boolean
1251 t is SpecialType && t.kind == 3;
1253 class UnionType extends ASTNode implements TypeExpr, Serializable {
1254 const types : [...TypeExpr];
1255 function UnionType (types)
1258 function serialize(s)
1259 s.sClass(this, "UnionType", "types");
1262 // "spread" may not be the best choice of name here.
1264 class ArrayType extends ASTNode implements TypeExpr, Serializable {
1265 const types : [...TypeExpr];
1266 const spread: ? TypeExpr;
1267 function ArrayType (types, spread)
1269 , spread = spread {}
1271 function serialize(s)
1272 s.sClass(this, "ArrayType", "types", "spread");
1275 // FIXME: Really redundant, except it introduces the tag TypeExpr
1276 // which might also be moved to Identifier and QualifiedIdentifier.
1277 // But keep for now until the type language settles down.
1279 class TypeName extends ASTNode implements TypeExpr, Serializable {
1280 const ident : IdentExpr;
1281 function TypeName (ident)
1284 function serialize(s)
1285 s.sClass(this, "TypeName", "ident");
1288 class ElementTypeRef extends ASTNode implements TypeExpr, Serializable {
1289 const base : TypeExpr;
1291 function ElementTypeRef (base,index)
1295 function serialize(s)
1296 s.sClass(this, "ElementTypeRef", "base", "index");
1299 class FieldTypeRef extends ASTNode implements TypeExpr, Serializable {
1300 const base : TypeExpr;
1301 const ident : IdentExpr;
1302 function FieldTypeRef (base,ident)
1306 function serialize(s)
1307 s.sClass(this, "FieldTypeRef", "base", "ident");
1310 class FunctionType extends ASTNode implements TypeExpr, Serializable {
1311 const typeParams: [...IDENT];
1312 const thisType : ? TypeExpr;
1313 const paramTypes: [...{ty:TypeExpr, optional:Boolean}];
1314 const hasRest : Boolean;
1315 const returnType: ? TypeExpr;
1316 function FunctionType(typeParams, thisType, paramTypes, hasRest, returnType)
1317 : typeParams = typeParams
1318 , thisType = thisType
1319 , paramTypes = paramTypes
1321 , returnType = returnType {}
1323 function serialize(s)
1324 s.sClass(this, "FunctionType", "typeParams", "thisType", "paramTypes", "hasRest", "returnType");
1327 class ObjectType extends ASTNode implements Serializable {
1328 const fields : [...FieldType];
1329 function ObjectType (fields)
1330 : fields = fields { }
1332 function serialize(s)
1333 s.sClass(this, "ObjectType", "fields");
1336 class FieldType extends ASTNode implements Serializable {
1339 function FieldType (ident,ty)
1343 function serialize(s)
1344 s.sClass(this, "FieldType", "ident", "ty");
1347 class AppType extends ASTNode implements TypeExpr, Serializable {
1348 const base : TypeExpr;
1349 const args : [...TypeExpr];
1350 function AppType (base,args)
1354 function serialize(s)
1355 s.sClass(this, "AppType", "base", "args");
1358 class NullableType extends ASTNode implements TypeExpr, Serializable {
1359 const ty : TypeExpr;
1360 const isNullable : Boolean;
1361 function NullableType (ty,isNullable)
1363 , isNullable = isNullable { }
1365 function serialize(s)
1366 s.sClass(this, "NullableType", "ty", "isNullable");
1369 class InstanceType extends ASTNode implements TypeExpr, Serializable {
1371 const typeParams : [...IDENT];
1372 const ty : TypeExpr;
1373 const isDynamic : Boolean;
1374 function InstanceType(name, typeParams, ty, isDynamic)
1376 , typeParams=typeParams
1378 , isDynamic=isDynamic
1381 function serialize(s)
1382 s.sClass(this, "InstanceType", "name", "typeParams", "ty", "isDynamic");
1385 class LikeType extends ASTNode implements Serializable {
1387 function LikeType(ty) : ty=ty {}
1389 function serialize(s)
1390 s.sClass(this, "LikeType", "ty");
1396 interface LabelSet {
1397 // Want to express (but can't): has 'labels': Array The best thing
1398 // we can do is either specify a push method, or a getter method
1402 class EmptyStmt extends ASTNode implements Stmt, Serializable {
1403 function serialize(s)
1404 s.sClass(this, "EmptyStmt");
1407 class ExprStmt extends ASTNode implements Stmt, Serializable {
1409 function ExprStmt (expr)
1412 function serialize(s)
1413 s.sClass(this, "ExprStmt", "expr");
1416 internal class ForInStmtCore extends ASTNode implements Stmt, LabelSet {
1417 const assignment: Expr;
1421 const is_each : boolean;
1422 const labels: [...IDENT];
1423 function ForInStmtCore (assignment,tmp,obj,stmt,is_each=false,labels=null)
1424 : assignment = assignment
1429 , labels = labels == null ? ([] : [...IDENT]) : labels {}
1432 class ForInStmt extends ForInStmtCore implements Serializable {
1433 function ForInStmt (assignment,tmp,obj,stmt,is_each=false,labels=null)
1434 : super(assignment, tmp, obj, stmt, is_each, labels) {}
1436 function serialize(s)
1437 s.sClass(this, "ForInStmt", "assignment", "tmp", "obj", "stmt", "is_each", "labels");
1440 class ForInBindingStmt extends ForInStmtCore implements Serializable {
1444 function ForInBindingStmt (head, assignment, tmp, init, obj, stmt,is_each=false,labels=null)
1447 , super(assignment, tmp, obj, stmt, is_each, labels) {}
1449 function serialize(s)
1450 s.sClass(this, "ForInBindingStmt", "head", "assignment", "tmp", "init", "obj", "stmt", "is_each", "labels");
1453 class ThrowStmt extends ASTNode implements Stmt, Serializable {
1455 function ThrowStmt (expr)
1458 function serialize(s)
1459 s.sClass(this, "ThrowStmt", "expr");
1462 class ReturnStmt extends ASTNode implements Stmt, Serializable {
1463 const expr : ? Expr;
1464 function ReturnStmt(expr)
1467 function serialize(s)
1468 s.sClass(this, "ReturnStmt", "expr");
1471 class BreakStmt extends ASTNode implements Stmt, Serializable {
1472 const ident : ? IDENT;
1473 function BreakStmt (ident)
1476 function serialize(s)
1477 s.sClass(this, "BreakStmt", "ident");
1480 class ContinueStmt extends ASTNode implements Stmt, Serializable {
1481 const ident : ? IDENT;
1482 function ContinueStmt (ident)
1485 function serialize(s)
1486 s.sClass(this, "ContinueStmt", "ident");
1489 class BlockStmt extends ASTNode implements Stmt, Serializable {
1490 const block : Block;
1491 function BlockStmt (block)
1494 function serialize(s)
1495 s.sClass(this, "BlockStmt", "block");
1498 class LabeledStmt extends ASTNode implements Stmt, Serializable {
1499 const label : IDENT;
1501 function LabeledStmt (label,stmt)
1505 function serialize(s)
1506 s.sClass(this, "LabeledStmt", "label", "stmt");
1509 class LetBlockStmt extends ASTNode implements Stmt, Serializable {
1510 const outer_head : Head;
1511 const inner_head : Head;
1512 const body : [...Stmt];
1513 function LetBlockStmt (outer_head,inner_head,body)
1514 : outer_head = outer_head
1515 , inner_head = inner_head
1518 function serialize(s)
1519 s.sClass(this, "LetBlockStmt", "outer_head", "inner_head", "body");
1522 class WhileStmt extends ASTNode implements Stmt, Serializable, LabelSet {
1525 const labels: [...IDENT];
1526 function WhileStmt (expr,stmt,labels=null)
1529 , labels = labels == null ? ([] : [...IDENT]) : labels {}
1531 function serialize(s)
1532 s.sClass(this, "WhileStmt", "expr", "stmt", "labels");
1535 class DoWhileStmt extends ASTNode implements Stmt, Serializable, LabelSet {
1538 const labels : [...IDENT];
1539 function DoWhileStmt (expr,stmt,labels=null)
1542 , labels = labels == null ? ([] : [...IDENT]) : labels {}
1544 function serialize(s)
1545 s.sClass(this, "DoWhileStmt", "expr", "stmt", "labels");
1548 internal class ForStmtCore extends ASTNode implements Stmt, LabelSet {
1549 const init : ? Expr;
1550 const cond : ? Expr;
1551 const incr : ? Expr;
1553 const labels : [...IDENT];
1554 function ForStmtCore (init,cond,incr,stmt,labels=null)
1559 , labels = labels == null ? ([] : [...IDENT]) : labels {}
1562 class ForStmt extends ForStmtCore implements Serializable {
1563 function ForStmt (init,cond,incr,stmt,labels=null)
1564 : super(init, cond, incr, stmt, labels) {}
1566 function serialize(s)
1567 s.sClass(this, "ForStmt", "init", "cond", "incr", "stmt", "labels");
1570 class ForBindingStmt extends ForStmtCore implements Serializable {
1572 function ForBindingStmt (head,init,cond,incr,stmt,labels=null)
1574 , super(init, cond, incr, stmt, labels) {}
1576 function serialize(s)
1577 s.sClass(this, "ForBindingStmt", "head", "init", "cond", "incr", "stmt", "labels");
1580 class IfStmt extends ASTNode implements Stmt, Serializable {
1582 const consequent : Stmt;
1583 const alternate : ? Stmt;
1584 function IfStmt (test, consequent, alternate)
1586 , consequent=consequent
1587 , alternate=alternate { }
1589 function serialize(s)
1590 s.sClass(this, "IfStmt", "test", "consequent", "alternate");
1593 class SwitchStmt extends ASTNode implements Stmt, Serializable {
1596 const cases : [...Case];
1597 function SwitchStmt (head, expr, cases)
1602 function serialize(s)
1603 s.sClass(this, "SwitchStmt", "head", "expr", "cases");
1606 class Case extends ASTNode implements Stmt, Serializable {
1607 const expr : ? Expr; // null for default
1608 const stmts : [...Stmt];
1609 function Case (expr,stmts)
1613 function serialize(s)
1614 s.sClass(this, "Case", "expr", "stmts");
1617 class WithStmt extends ASTNode implements Stmt, Serializable {
1620 function WithStmt (expr,stmt)
1624 function serialize(s)
1625 s.sClass(this, "WithStmt", "expr", "stmt");
1628 class TryStmt extends ASTNode implements Stmt, Serializable {
1629 const block : Block;
1630 const catches : [...Catch];
1631 const finallyBlock : ? Block;
1632 function TryStmt (block,catches,finallyBlock)
1635 , finallyBlock = finallyBlock { }
1637 function serialize(s)
1638 s.sClass(this, "TryStmt", "block", "catches", "finallyBlock");
1641 class SwitchTypeStmt extends ASTNode implements Stmt, Serializable {
1643 const cases: [...Catch];
1644 function SwitchTypeStmt (expr,cases)
1648 function serialize(s)
1649 s.sClass(this, "SwitchTypeStmt", "expr", "cases");
1652 class Catch extends ASTNode implements Serializable {
1655 function Catch (param,block)
1659 function serialize(s)
1660 s.sClass(this, "Catch", "param", "block");
1663 class SuperStmt extends ASTNode implements Stmt, Serializable {
1664 const args : [...Expr];
1665 const spread: ? Expr;
1666 function SuperStmt(args, spread)
1670 function serialize(s)
1671 s.sClass(this, "SuperStmt", "args", "spread");
1674 class Block extends ASTNode implements Serializable {
1675 const head : ? Head;
1676 const stmts : [...Stmt];
1677 function Block (head,stmts)
1681 function serialize(s)
1682 s.sClass(this, "Block", "head", "stmts");
1689 class Program extends ASTNode implements Serializable {
1690 const body : [...Stmt];
1692 const file : ? String;
1693 const attr : FuncAttr;
1694 function Program (body, head, attr, file=null)
1700 function serialize(s)
1701 s.sClass(this, "Program", "body", "head", "attr", "file");
1706 const tokenToOperator = [];
1709 tokenToOperator[Token::Equal] = Ast::equalOp;
1710 tokenToOperator[Token::NotEqual] = Ast::notEqualOp;
1711 tokenToOperator[Token::StrictEqual] = Ast::strictEqualOp;
1712 tokenToOperator[Token::StrictNotEqual] = Ast::strictNotEqualOp;
1713 tokenToOperator[Token::LessThan] = Ast::lessOp;
1714 tokenToOperator[Token::GreaterThan] = Ast::greaterOp;
1715 tokenToOperator[Token::LessThanOrEqual] = Ast::lessOrEqualOp;
1716 tokenToOperator[Token::GreaterThanOrEqual] = Ast::greaterOrEqualOp;
1717 tokenToOperator[Token::In] = Ast::inOp;
1718 tokenToOperator[Token::InstanceOf] = Ast::instanceOfOp;
1719 tokenToOperator[Token::Is] = Ast::isOp;
1720 tokenToOperator[Token::Cast] = Ast::castOp;
1721 tokenToOperator[Token::Like] = Ast::likeOp;
1722 tokenToOperator[Token::LeftShift] = Ast::leftShiftOp;
1723 tokenToOperator[Token::RightShift] = Ast::rightShiftOp;
1724 tokenToOperator[Token::UnsignedRightShift] = Ast::rightShiftUnsignedOp;
1725 tokenToOperator[Token::Plus] = Ast::plusOp;
1726 tokenToOperator[Token::Minus] = Ast::minusOp;
1727 tokenToOperator[Token::Mult] = Ast::timesOp;
1728 tokenToOperator[Token::Div] = Ast::divideOp;
1729 tokenToOperator[Token::Remainder] = Ast::remainderOp;
1730 tokenToOperator[Token::Delete] = Ast::deleteOp;
1731 tokenToOperator[Token::Assign] = Ast::assignOp;
1732 tokenToOperator[Token::PlusAssign] = Ast::assignPlusOp;
1733 tokenToOperator[Token::MinusAssign] = Ast::assignMinusOp;
1734 tokenToOperator[Token::MultAssign] = Ast::assignTimesOp;
1735 tokenToOperator[Token::DivAssign] = Ast::assignDivideOp;
1736 tokenToOperator[Token::RemainderAssign] = Ast::assignRemainderOp;
1737 tokenToOperator[Token::BitwiseAndAssign] = Ast::assignBitwiseAndOp;
1738 tokenToOperator[Token::BitwiseOrAssign] = Ast::assignBitwiseOrOp;
1739 tokenToOperator[Token::BitwiseXorAssign] = Ast::assignBitwiseXorOp;
1740 tokenToOperator[Token::LeftShiftAssign] = Ast::assignLeftShiftOp;
1741 tokenToOperator[Token::RightShiftAssign] = Ast::assignRightShiftOp;
1742 tokenToOperator[Token::UnsignedRightShiftAssign] = Ast::assignRightShiftUnsignedOp;
1743 tokenToOperator[Token::LogicalAndAssign] = Ast::assignLogicalAndOp;
1744 tokenToOperator[Token::LogicalOrAssign] = Ast::assignLogicalOrOp;
1747 tokenToOperator[Token::Delete + 1000] = Ast::deleteOp;
1748 tokenToOperator[Token::PlusPlus + 1000] = Ast::preIncrOp;
1749 tokenToOperator[Token::MinusMinus + 1000] = Ast::preDecrOp;
1750 tokenToOperator[Token::Void + 1000] = Ast::voidOp;
1751 tokenToOperator[Token::TypeOf + 1000] = Ast::typeOfOp;
1752 tokenToOperator[Token::Plus + 1000] = Ast::unaryPlusOp;
1753 tokenToOperator[Token::Minus + 1000] = Ast::unaryMinusOp;
1754 tokenToOperator[Token::BitwiseNot + 1000] = Ast::bitwiseNotOp;
1755 tokenToOperator[Token::Not + 1000] = Ast::logicalNotOp;
1757 //////////////////////////////////////////////////////////////////////
1762 use default namespace internal,
1767 public function Serializer(compact=false) : compact=compact {}
1769 public function serialize(obj) {
1770 if (obj is Serializable)
1771 return obj.serialize(this);
1774 return serializeArray(obj, true);
1776 if (obj is Number || obj is Boolean || obj is int || obj is uint || obj === null || obj === undefined)
1780 return "'" + sanitize(obj) + "'";
1782 //throw new Error("Unserializable datum " + obj);
1783 return "[[" + obj + "]]";
1786 function serializeArray(obj, linebreak) {
1788 let separator = !compact && linebreak ? "\n," : ",";
1789 let lastWasOK = true;
1790 for ( let i=0, limit=obj.length ; i < limit ; i++ ) {
1794 if (obj.hasOwnProperty(i)) {
1796 s += serialize(obj[i]);
1805 function sanitize(s) {
1813 let c = s.charCodeAt(i);
1815 c == Char::BackSlash ||
1816 c == Char::SingleQuote ||
1817 c == Char::DoubleQuote ||
1818 c == Char::UnicodePS ||
1819 c == Char::UnicodeLS) {
1820 r += s.substring(start, i);
1827 r += s.substring(start, i);
1833 "\\u" + (c+0x10000).toString(16).substring(1);
1835 public function sClass(obj, ...rest) {
1836 // The 'ast_layout' is reduced to the class name the day
1837 // Tamarin performs enumeration/itemization in insertion
1838 // order. If size concerns us (not likely) then we can
1839 // compress by maintaining an indexed dictionary of
1840 // layout arrays, which is emitted as part of the output.
1842 let sep0 = compact ? "" : "\n, ";
1843 let sep1 = compact ? "," : "\n, ";
1846 s += "{/*" + rest[0] + "*/ ";
1848 s += "{ 'ast_layout': " + serializeArray(rest, false);
1849 for ( let i=1, limit=rest.length ; i < limit ; i++ ) {
1850 s += (i > 1 ? sep1 : sep0) + "'" + rest[i] + "': ";
1851 s += serialize(obj[rest[i]]);
1857 public function sConstant(expr)
1858 "{ 'ast_constant': '" + expr + "' }";
1862 // The unserializer uses 'eval' for three things:
1863 // - to decode the JSON input (dangerous)
1864 // - to create constructor functions for classes
1865 // - to look up global constant properties
1867 // The latter two could be gotten rid of by using
1869 // new Ast::[tag](...desc.map(decode))
1875 // respectively (if the serializer cooperates; right now the
1876 // constName expression is not a name so that wouldn't work),
1877 // but for that we need bracket syntax and splat to work.
1880 // The function 'globalEval' should be removed and invocations
1881 // of it should be replaced simply by 'global.eval', but that
1882 // requires a working notion of 'global' in tamarin.
1884 class Unserializer {
1885 use default namespace internal,
1888 public function unserializeText(s)
1889 decode(globalEval("(" + s + ")"));
1891 public function unserializeObject(obj)
1894 function decode(x) {
1895 if (x is Boolean || x is Number || x is int || x is uint || x is String)
1899 for ( let i=0, limit=x.length ; i < limit ; i++ )
1900 if (x.hasOwnProperty(i))
1901 x[i] = decode(x[i]);
1905 if (x.hasOwnProperty("ast_layout")) {
1906 let desc = x.ast_layout;
1909 return (getConstructor(tag, desc.length)).apply(null, Util::map(function (n) { return decode(x[n]) }, desc));
1912 if (x.hasOwnProperty("ast_constant"))
1913 return globalEval(x.ast_constant);
1917 if (x.hasOwnProperty(n))
1918 s += "'" + n + "': " + x[n];
1920 throw new Error("Unknown datum type: object without a tag: " + s);
1923 // A map from name to function that constructs instance of name.
1924 var constructors = {};
1926 function getConstructor(name, arity) {
1927 if (!constructors.hasOwnProperty(name)) {
1928 // FIXME: An array comprehension would be pretty here...
1930 for ( let i=0 ; i < arity ; i++ )
1931 args.push("_p" + i);
1932 constructors[name] = globalEval("(function (" + args + ") { return new Ast::" + name + "(" + args + ") })");
1934 return constructors[name];
1937 function globalEval(s)
1938 ESC::evaluateInScopeArray([s], [], "");