├── .gitignore ├── AST ├── CAccess.cs ├── CArgument.cs ├── CArgumentList.cs ├── CArrayClass.cs ├── CAsst.cs ├── CAttribute.cs ├── CAttributeList.cs ├── CBaseAccess.cs ├── CBinaryOperator.cs ├── CCase.cs ├── CCast.cs ├── CCatch.cs ├── CClass.cs ├── CClassConst.cs ├── CComment.cs ├── CComparison.cs ├── CConcat.cs ├── CConst.cs ├── CConstantExpression.cs ├── CDefaultAccess.cs ├── CDictionaryType.cs ├── CDim.cs ├── CDirective.cs ├── CDo.cs ├── CEnum.cs ├── CExit.cs ├── CExpression.cs ├── CExpressionStatement.cs ├── CField.cs ├── CFile.cs ├── CFinally.cs ├── CFor.cs ├── CForEach.cs ├── CFunction.cs ├── CFunctionType.cs ├── CGlobalAccess.cs ├── CHtml.cs ├── CIf.cs ├── CIgnore.cs ├── CInterface.cs ├── CLambdaExpression.cs ├── CLambdaFunction.cs ├── CLock.cs ├── CLogic.cs ├── CMath.cs ├── CMathUnary.cs ├── CMember.cs ├── CMemberAccess.cs ├── CMemberOverload.cs ├── CMemberVariable.cs ├── CMethod.cs ├── CNew.cs ├── CNewline.cs ├── CNode.cs ├── CNot.cs ├── COnError.cs ├── COnExit.cs ├── COption.cs ├── COptionalByRef.cs ├── CParameters.cs ├── CParenExpression.cs ├── CPictureOfExpression.cs ├── CProgram.cs ├── CProperty.cs ├── CReDim.cs ├── CReturn.cs ├── CScope.cs ├── CSelect.cs ├── CSpecialEqual.cs ├── CStatement.cs ├── CStatementBlock.cs ├── CTernary.cs ├── CThisAccess.cs ├── CThrow.cs ├── CToken.cs ├── CTry.cs ├── CTypeRef.cs ├── CUnaryOperator.cs ├── CUnionClass.cs ├── CVariable.cs ├── CVariableBase.cs ├── CWhile.cs ├── CWith.cs ├── CWithAccess.cs ├── IAttributed.cs ├── IHasVisibility.cs ├── IVariable.cs ├── IVisitor.cs └── TokenTypes.cs ├── App.config ├── BuiltIns.cs ├── ClrImporter.cs ├── CodeGenVisitor.cs ├── CompileException.cs ├── Compiler.cs ├── Example ├── App.config ├── Example.csproj ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── ICodeGenVisitor.cs ├── LICENSE ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── README.md ├── RoslynExtensions.cs ├── RoslynGenerator.cs ├── WasabiRoslynGenerator.csproj ├── WasabiRoslynGenerator.sln ├── packages.config └── was_out └── .gitignore /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.user 3 | *.userprefs 4 | [Bb]in/ 5 | [Oo]bj/ 6 | x64/ 7 | x86/ 8 | 9 | # NuGet Packages 10 | *.nupkg 11 | # The packages folder can be ignored because of Package Restore 12 | **/packages/* 13 | # except build/, which is used as an MSBuild target. 14 | !**/packages/build/ 15 | -------------------------------------------------------------------------------- /AST/CAccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CAccess : CExpression 7 | { 8 | private CToken referenceToken; 9 | private bool isRootAccess; 10 | private bool isMemberSource; 11 | private bool isCallExplicit; 12 | private bool isCallImplicit; 13 | private CNode referenceTarget; 14 | 15 | 16 | public CAccess(CToken tok, CToken item) 17 | : base(tok) 18 | { 19 | referenceToken = item; 20 | isMemberSource = false; 21 | isRootAccess = true; 22 | } 23 | 24 | public bool IsRootAccess 25 | { 26 | get { return isRootAccess; } 27 | protected set { isRootAccess = value; } 28 | } 29 | 30 | public bool IsMemberSource 31 | { 32 | get { return isMemberSource; } 33 | set { isMemberSource = value; } 34 | } 35 | 36 | public CNode ReferenceTarget 37 | { 38 | get { return referenceTarget; } 39 | set { referenceTarget = value; } 40 | } 41 | 42 | public CToken ReferenceToken 43 | { 44 | get { return referenceToken; } 45 | protected set { referenceToken = value; } 46 | } 47 | 48 | /// 49 | /// Both IsCallExplicit and IsCallImplicit exist. However, they are not mutually exclusive opposites, so they cannot 50 | /// be condensed down into one method. 51 | /// 52 | public bool IsCallExplicit 53 | { 54 | get { return isCallExplicit; } 55 | set { isCallExplicit = value; } 56 | } 57 | 58 | /// 59 | /// Both IsCallExplicit and IsCallImplicit exist. However, they are not mutually exclusive opposites, so they cannot 60 | /// be condensed down into one method. 61 | /// 62 | public bool IsCallImplicit 63 | { 64 | get { return isCallImplicit; } 65 | set { isCallImplicit = value; } 66 | } 67 | 68 | public override void Accept(IVisitor visit) 69 | { 70 | visit.VisitAccess(this); 71 | } 72 | 73 | public override bool IsConstant 74 | { 75 | get 76 | { 77 | return (ReferenceTarget is CConst) || (ReferenceTarget is CClassConst) || ((ReferenceTarget is CExpression) && ((CExpression)ReferenceTarget).IsConstant); 78 | } 79 | } 80 | 81 | public bool ForceGlobalAccess 82 | { 83 | get; 84 | set; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /AST/CArgument.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CArgument : CVariableBase, IVariable 7 | { 8 | private CToken direction; 9 | 10 | private Mono.Cecil.ParameterDefinition cecilParameter; 11 | 12 | private bool indexerValueArgument = false; 13 | 14 | public bool IndexerValueArgument 15 | { 16 | get { return indexerValueArgument; } 17 | set { indexerValueArgument = value; } 18 | } 19 | 20 | public Mono.Cecil.ParameterDefinition CecilParameter 21 | { 22 | get { return cecilParameter; } 23 | set { cecilParameter = value; } 24 | } 25 | 26 | public CArgument(CToken direction, CToken name, CTypeRef tref) 27 | : base(name) 28 | { 29 | this.direction = direction; 30 | this.name = name; 31 | base.LoadType(tref); 32 | } 33 | 34 | public bool Optional 35 | { 36 | get { return Attributes.contains("optional"); } 37 | } 38 | 39 | // Optional is a reserved word in Wasabi 40 | public bool IsOptional 41 | { 42 | get { return Optional; } 43 | } 44 | 45 | public CExpression DefaultValue 46 | { 47 | get 48 | { 49 | if (Attributes.contains("optional")) 50 | { 51 | CAttribute attrib = Attributes["optional"]; 52 | if (attrib.Parameters.Unnamed.Count != 0) 53 | return (CExpression)attrib.Parameters[0]; 54 | } 55 | return null; 56 | } 57 | } 58 | 59 | public CToken Direction 60 | { 61 | get { return direction; } 62 | } 63 | 64 | public override bool IsField 65 | { 66 | get { return false; } 67 | set { throw new NotImplementedException(); } 68 | } 69 | 70 | public override void Accept(IVisitor visitor) 71 | { 72 | } 73 | 74 | public string ToArgumentString() 75 | { 76 | string s1 = ""; 77 | if (Optional) s1 = "Optional "; 78 | string s2 = ""; 79 | if (Direction.Value == "byref") 80 | s2 = "ByRef "; 81 | else if (Direction.Value == "byval") 82 | s2 = "ByVal "; 83 | string s3 = ""; 84 | if (Type != null && Type.TypeName != null && !String.IsNullOrEmpty(Type.TypeName.RawValue)) 85 | { 86 | string sName = Type.TypeName.RawValue; 87 | string sParens = ""; 88 | while (sName.EndsWith("()")) 89 | { 90 | sParens += "()"; 91 | sName = sName.Substring(0, sName.Length - 2); 92 | } 93 | s3 = sParens + " As [" + sName + "]"; 94 | } 95 | return s1 + s2 + Name.RawValue + s3; 96 | } 97 | 98 | public string ToParameterString() 99 | { 100 | return Name.RawValue; 101 | } 102 | 103 | public string ToTypeString() 104 | { 105 | string sTypeName = Type.TypeName.RawValue; 106 | 107 | string sParens = ""; 108 | while (sTypeName.EndsWith("()")) 109 | { 110 | sParens += "[]"; 111 | sTypeName = sTypeName.Substring(0, sTypeName.Length - 2); 112 | } 113 | 114 | System.Type systype = System.Type.GetType("System." + sTypeName); 115 | if (systype != null) 116 | return systype.FullName + sParens; 117 | else 118 | return sTypeName + sParens; 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /AST/CArgumentList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace FogCreek.Wasabi.AST 7 | { 8 | public class CArgumentList : IEnumerable 9 | { 10 | private Dictionary argTable; 11 | private List args = new List(); 12 | private bool _semanticallyComplete = false; 13 | private int? minParams; 14 | private int? maxParams; 15 | 16 | public void Add(CArgument arg) 17 | { 18 | minParams = maxParams = null; 19 | args.Add(arg); 20 | } 21 | 22 | public CArgument this[int ix] 23 | { 24 | get { return args[ix]; } 25 | } 26 | 27 | public CArgument this[string name] 28 | { 29 | get 30 | { 31 | BuildArgTable(); 32 | CArgument arg = null; 33 | argTable.TryGetValue(name, out arg); 34 | return arg; 35 | } 36 | } 37 | 38 | private void BuildArgTable() 39 | { 40 | if (argTable != null) return; 41 | argTable = new Dictionary(StringComparer.InvariantCultureIgnoreCase); 42 | foreach (CArgument arg in args) 43 | { 44 | argTable[arg.Name.Value] = arg; 45 | } 46 | } 47 | 48 | public CArgumentList GetRange(int index, int count) 49 | { 50 | CArgumentList newlist = new CArgumentList(); 51 | newlist.args = args.GetRange(index, count); 52 | return newlist; 53 | } 54 | 55 | public int MinAllowedParameters 56 | { 57 | get 58 | { 59 | if (!minParams.HasValue) 60 | { 61 | GetMinMax(); 62 | } 63 | return minParams.Value; 64 | } 65 | } 66 | 67 | public int MaxAllowedParameters 68 | { 69 | get 70 | { 71 | if (!maxParams.HasValue) 72 | { 73 | GetMinMax(); 74 | } 75 | return maxParams.Value; 76 | } 77 | } 78 | 79 | private void GetMinMax() 80 | { 81 | maxParams = 0; 82 | minParams = 0; 83 | foreach (CArgument arg in args) 84 | { 85 | bool paramarray = arg.Attributes.contains("paramarray"); 86 | if (!arg.Optional && !paramarray) 87 | minParams++; 88 | if (!paramarray) 89 | maxParams++; 90 | else 91 | maxParams = int.MaxValue >> 1; 92 | } 93 | } 94 | 95 | public int Count 96 | { 97 | get { return args.Count; } 98 | } 99 | 100 | public bool SemanticallyComplete() 101 | { 102 | return _semanticallyComplete; 103 | } 104 | 105 | public void SetSemanticallyComplete() 106 | { 107 | _semanticallyComplete = true; 108 | } 109 | 110 | public void ResetSemanticallyComplete() 111 | { 112 | _semanticallyComplete = false; 113 | } 114 | 115 | #region IEnumerable Members 116 | 117 | IEnumerator IEnumerable.GetEnumerator() 118 | { 119 | return args.GetEnumerator(); 120 | } 121 | 122 | #endregion 123 | 124 | #region IEnumerable Members 125 | 126 | IEnumerator IEnumerable.GetEnumerator() 127 | { 128 | return args.GetEnumerator(); 129 | } 130 | 131 | #endregion 132 | 133 | public IEnumerable Nodes() 134 | { 135 | foreach (CArgument arg in args) 136 | yield return arg; 137 | } 138 | 139 | public string ToArgumentString() 140 | { 141 | List sargs = args.ConvertAll(delegate(CArgument arg) { return arg.ToArgumentString(); }); 142 | return String.Join(", ", sargs.ToArray()); 143 | } 144 | 145 | public string ToParameterString() 146 | { 147 | List sargs = args.ConvertAll(delegate(CArgument arg) { return arg.ToParameterString(); }); 148 | return String.Join(", ", sargs.ToArray()); 149 | } 150 | 151 | public string ToTypeString() 152 | { 153 | List sargs = args.ConvertAll(delegate(CArgument arg) { return arg.ToTypeString(); }); 154 | return String.Join(", ", sargs.ToArray()); 155 | } 156 | 157 | internal bool Contains(string p) 158 | { 159 | foreach (CArgument arg in args) 160 | if (arg.Name.Value == p) 161 | return true; 162 | return false; 163 | } 164 | 165 | internal int IndexOf(CArgument arg) 166 | { 167 | return args.IndexOf(arg); 168 | } 169 | } 170 | } -------------------------------------------------------------------------------- /AST/CArrayClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CArrayType : CClass 7 | { 8 | private static int i = 1; 9 | 10 | private int dims; 11 | protected CTypeRef indexType; 12 | private int id; 13 | private CTypeRef itemType; 14 | 15 | protected virtual string NamePrefix 16 | { 17 | get { return "Array"; } 18 | } 19 | 20 | public override CAttributeList Attributes 21 | { 22 | get 23 | { 24 | CAttributeList cal = base.Attributes; 25 | if (!cal.contains("ExecuteAnywhere") && !cal.contains("ExecuteOnClient") && !cal.contains("ExecuteOnServer") && !cal.contains("ExecuteAtCompiler")) 26 | cal.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(this, CProgram.Global.FindClass("ExecuteAnywhereAttribute"))); 27 | return cal; 28 | } 29 | } 30 | 31 | protected virtual string Open { get { return "("; } } 32 | protected virtual string Close { get { return ")"; } } 33 | 34 | public virtual CTypeRef ItemType 35 | { 36 | get { return itemType; } 37 | set 38 | { 39 | itemType.InternalLoad(value); 40 | if (itemType.Resolved) 41 | SetSemanticallyComplete(); 42 | 43 | if (ReferenceEquals(value.ActualType, this)) 44 | throw new InvalidOperationException("Array ItemType circular reference"); 45 | 46 | 47 | string name = (itemType.Resolved ? "" : NamePrefix) 48 | + (itemType.TypeName != null ? itemType.TypeName.RawValue : id.ToString()) 49 | + Open + new String(',', dims-1) + Close; 50 | NameToken = CToken.Identifer(NameToken, name, name); 51 | 52 | foreach (CArrayType link in linked) 53 | { 54 | if (link.ItemType.Resolved && link.ItemType != this.ItemType) 55 | throw new InvalidOperationException("IndexedType missinferred"); 56 | 57 | if (!link.ItemType.Resolved) 58 | link.itemType = value; 59 | } 60 | } 61 | } 62 | 63 | public virtual bool CanBeRedimed 64 | { 65 | get { return true; } 66 | } 67 | 68 | public CTypeRef IndexType 69 | { 70 | get { return indexType; } 71 | } 72 | 73 | public int Dimensions 74 | { 75 | get { return dims; } 76 | } 77 | 78 | public CArrayType(int dims) 79 | : base("Array<" + (++i) + "," + dims + ">", false) 80 | { 81 | id = i; 82 | 83 | this.dims = dims; 84 | IsObject = false; 85 | indexType = new CTypeRef(this, BuiltIns.Int32); 86 | itemType = new CTypeRef(this); 87 | 88 | if (Compiler.Current != null) 89 | CProgram.Global.AddArray(this); 90 | } 91 | 92 | public override CTypeRef BaseClass 93 | { 94 | get 95 | { 96 | if (NamePrefix == "Array" && (!base.BaseClass.Resolved || base.BaseClass.ActualType == BuiltIns.Variant)) 97 | base.ForceSetBaseClass(CProgram.Global.FindClass("System.Array")); 98 | return base.BaseClass; 99 | } 100 | } 101 | 102 | public CArrayType(CTypeRef type, int dims) 103 | : this(dims) 104 | { 105 | ItemType = type; 106 | } 107 | 108 | protected override bool canArrayConvert(CArrayType klass) 109 | { 110 | if (IndexType == klass.IndexType && ItemType.Resolved) 111 | return ItemType.ActualType.canConvertTo(klass.ItemType); 112 | return false; 113 | } 114 | 115 | public override bool Equals(Object obj) 116 | { 117 | if (!(obj is CArrayType)) 118 | return false; 119 | 120 | if (ReferenceEquals(obj, this)) 121 | return true; 122 | 123 | CArrayType other = (CArrayType)obj; 124 | 125 | if (NamePrefix != other.NamePrefix) 126 | return false; 127 | 128 | if (!itemType.Resolved || !other.itemType.Resolved) 129 | return false; 130 | 131 | if (!indexType.Equals(other.indexType)) 132 | return false; 133 | 134 | if (dims != other.dims) 135 | return false; 136 | 137 | return itemType.Equals(other.itemType); 138 | } 139 | 140 | public override int GetHashCode() 141 | { 142 | return 123456789; 143 | } 144 | 145 | List linked = new List(); 146 | internal void Link(CArrayType aFrom) 147 | { 148 | linked.Add(aFrom); 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /AST/CAsst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | // this class is for statements in the original vb code that are assignment statements. 7 | // assignment statements have a left hand side and a right hand side 8 | public class CAssignment : CStatement, INodeParent 9 | { 10 | private CAccess lhs; // the left hand side of the assignment statement 11 | private CExpression rhs; // the right hand side of it 12 | 13 | // this is a special case from the normal object types. we are actually being a given an 14 | // object of type CExpression to parse rather than just the lex stream. 15 | public CAssignment(CToken token) 16 | : base(token) {} 17 | 18 | public CAccess Target 19 | { 20 | get { return lhs; } 21 | set 22 | { 23 | lhs = value; 24 | lhs.Parent = this; 25 | lhs.LhsAssignmentTarget = true; 26 | } 27 | } 28 | 29 | public CExpression Source 30 | { 31 | get { return rhs; } 32 | set 33 | { 34 | rhs = value; 35 | rhs.Parent = this; 36 | rhs.RhsAssignmentSource = true; 37 | } 38 | } 39 | 40 | public override void Accept(IVisitor visitor) 41 | { 42 | visitor.VisitAssignment(this); 43 | } 44 | 45 | void INodeParent.Replace(CNode child, CNode newchild) 46 | { 47 | if (lhs == child) 48 | lhs = (CAccess)newchild; 49 | if (rhs == child) 50 | rhs = (CExpression)newchild; 51 | newchild.Parent = this; 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /AST/CAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FogCreek.Wasabi.AST 4 | { 5 | public class CAttribute : CNode 6 | { 7 | private readonly string name; 8 | private readonly CToken nameToken; 9 | private readonly CParameters parameters; 10 | 11 | public CAttribute(CToken name, CParameters parameters, CTypeRef ctr) 12 | : base(name) 13 | { 14 | this.name = name.Value; 15 | nameToken = name; 16 | this.parameters = parameters ?? new CParameters(); 17 | LoadType(new CTypeRef(this, ctr)); 18 | } 19 | 20 | public string Name 21 | { 22 | get { return name; } 23 | } 24 | 25 | public CToken NameToken 26 | { 27 | get { return nameToken; } 28 | } 29 | 30 | public CParameters Parameters 31 | { 32 | get { return parameters; } 33 | } 34 | 35 | public override void Accept(IVisitor visitor) 36 | { 37 | visitor.VisitAttribute(this); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /AST/CAttributeList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CAttributeList : IEnumerable 8 | { 9 | internal List list = new List(); 10 | 11 | public int Count 12 | { 13 | get { return list.Count; } 14 | } 15 | 16 | public void Add(CToken name, CTypeRef ctr) 17 | { 18 | Add(name, null, ctr); 19 | } 20 | 21 | public void Add(CToken name, CParameters parameters, CTypeRef ctr) 22 | { 23 | list.Add(new CAttribute(name, parameters, ctr)); 24 | } 25 | 26 | public void Add(CAttributeList attribs) 27 | { 28 | if (attribs != null) 29 | list.AddRange(attribs.list); 30 | } 31 | 32 | protected void Add(CAttribute attrib) 33 | { 34 | list.Add(attrib); 35 | } 36 | 37 | private static readonly CAttributeList empty = new CAttributeList(); 38 | 39 | public CAttributeList getList(String name) 40 | { 41 | if (list.Count == 0) 42 | return empty; 43 | 44 | CAttributeList result = new CAttributeList(); 45 | foreach (CAttribute attribute in list) 46 | { 47 | if (NameEquals(attribute.Name, name)) 48 | result.Add(attribute); 49 | } 50 | 51 | return result; 52 | } 53 | 54 | private bool NameEquals(string p, string name) 55 | { 56 | return p.Equals(name, StringComparison.OrdinalIgnoreCase) || 57 | (p + "Attribute").Equals(name, StringComparison.OrdinalIgnoreCase) || 58 | p.Equals(name + "Attribute", StringComparison.OrdinalIgnoreCase); 59 | } 60 | 61 | public CAttributeList getList() 62 | { 63 | if (list.Count == 0) 64 | return empty; 65 | 66 | CAttributeList result = new CAttributeList(); 67 | foreach (CAttribute attribute in list) 68 | result.Add(attribute); 69 | 70 | return result; 71 | } 72 | 73 | public bool contains(String name) 74 | { 75 | if (list.Count == 0) 76 | return false; 77 | name = name.ToLower(); 78 | for (int i = 0; i < list.Count; i++) 79 | { 80 | if (NameEquals(this[i].Name, name)) 81 | return true; 82 | } 83 | return false; 84 | } 85 | 86 | 87 | public bool containsMultiple(string name) 88 | { 89 | if (list.Count < 2) 90 | return false; 91 | name = name.ToLower(); 92 | 93 | int found = 0; 94 | 95 | for (int i = 0; i < list.Count; i++) 96 | { 97 | if (NameEquals(this[i].Name, name)) 98 | found++; 99 | if (found > 1) 100 | return true; 101 | } 102 | return false; 103 | } 104 | 105 | public bool CanVisit(NodeStateMode mode, bool fAlsoExistsOnClient) 106 | { 107 | if (mode == NodeStateMode.Client) 108 | { 109 | return contains("executeanywhere") 110 | || contains("executeonclient") 111 | || contains("executeonserver") 112 | || (fAlsoExistsOnClient && contains("alsoexistsonclient")); 113 | } 114 | else if (mode == NodeStateMode.Server) 115 | { 116 | return contains("executeanywhere") 117 | || !contains("executeonclient"); 118 | } 119 | else 120 | throw new InvalidOperationException("Unknown mode!"); 121 | } 122 | 123 | 124 | public CAttribute this[object nameOrIx] 125 | { 126 | get 127 | { 128 | if (nameOrIx is String) 129 | return this[(String)nameOrIx]; 130 | else 131 | return this[Convert.ToInt32(nameOrIx)]; 132 | } 133 | } 134 | 135 | public CAttribute this[string name] 136 | { 137 | get 138 | { 139 | if (list.Count == 0) 140 | return null; 141 | for (int i = 0; i < list.Count; i++) 142 | { 143 | if (this[i].Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) 144 | return this[i]; 145 | } 146 | for (int i = 0; i < list.Count; i++) 147 | { 148 | if ((this[i].Name + "Attribute").Equals(name, StringComparison.InvariantCultureIgnoreCase) || (this[i].Name).Equals(name + "Attribute", StringComparison.InvariantCultureIgnoreCase)) 149 | return this[i]; 150 | } 151 | return null; 152 | } 153 | } 154 | 155 | public CAttribute this[int ix] 156 | { 157 | get { return list[ix]; } 158 | } 159 | 160 | /// 161 | ///Returns an enumerator that iterates through the collection. 162 | /// 163 | /// 164 | /// 165 | ///A that can be used to iterate through the collection. 166 | /// 167 | ///1 168 | IEnumerator IEnumerable.GetEnumerator() 169 | { 170 | return list.GetEnumerator(); 171 | } 172 | 173 | /// 174 | ///Returns an enumerator that iterates through a collection. 175 | /// 176 | /// 177 | /// 178 | ///An object that can be used to iterate through the collection. 179 | /// 180 | ///2 181 | IEnumerator IEnumerable.GetEnumerator() 182 | { 183 | return list.GetEnumerator(); 184 | } 185 | } 186 | } -------------------------------------------------------------------------------- /AST/CBaseAccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CBaseAccess : CAccess 7 | { 8 | public CBaseAccess(CToken tok) 9 | : base(tok, tok) 10 | { 11 | } 12 | 13 | public override void Accept(IVisitor visit) 14 | { 15 | visit.VisitBaseAccess(this); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /AST/CBinaryOperator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public abstract class CBinaryOperator : CExpression, INodeParent 7 | { 8 | private CToken operation; 9 | private CExpression lhs; 10 | private CExpression rhs; 11 | 12 | public CBinaryOperator(CToken tok, CExpression lhs, CExpression rhs) 13 | : base(tok) 14 | { 15 | operation = tok; 16 | this.lhs = lhs; 17 | this.rhs = rhs; 18 | lhs.Parent = this; 19 | rhs.Parent = this; 20 | } 21 | 22 | public override bool IsConstant 23 | { 24 | get 25 | { 26 | return lhs.IsConstant && rhs.IsConstant; 27 | } 28 | } 29 | 30 | public CToken Operation 31 | { 32 | get { return operation; } 33 | } 34 | 35 | public CExpression Left 36 | { 37 | get { return lhs; } 38 | } 39 | 40 | public CExpression Right 41 | { 42 | get { return rhs; } 43 | } 44 | 45 | void INodeParent.Replace(CNode child, CNode newchild) 46 | { 47 | if (lhs == child) 48 | lhs = (CExpression)newchild; 49 | if (rhs == child) 50 | rhs = (CExpression)newchild; 51 | newchild.Parent = this; 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /AST/CCase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | // this class is for the specific cases of a switch statement 7 | public class CCase : CStatement, INodeParent 8 | { 9 | private CExpression m_value; // in the line case('prephase') then 'prephase' is the vaue 10 | private CStatementBlock statements; // the statements to be executed in this case of the switch 11 | private bool elseCaseFlag; // flag indicating if this case is the default case 12 | 13 | 14 | // if statements is null, that means there are no statements. meaning this case uses the statements 15 | // of the case below it. so dont put a break point. eg: 16 | // switch (color) { 17 | // case (red): 18 | // case (blue): 19 | // print("its red or blue); 20 | // break; 21 | // 22 | public CCase(CToken token, CExpression val) 23 | : base(token) 24 | { 25 | m_value = val; 26 | m_value.Parent = this; 27 | statements = null; 28 | } 29 | 30 | // this is the constructor when you actually need to parse all the statements of a case 31 | // until you hit the next case 32 | public CCase(CToken token, CExpression val, CStatementBlock block) 33 | : base(token) 34 | { 35 | m_value = val; 36 | elseCaseFlag = val == null; 37 | if (!elseCaseFlag) 38 | m_value.Parent = this; 39 | statements = block; 40 | } 41 | 42 | public bool IsElseCase 43 | { 44 | get { return elseCaseFlag; } 45 | } 46 | 47 | public CStatementBlock Statements 48 | { 49 | get { return statements; } 50 | } 51 | 52 | public CExpression Value 53 | { 54 | get { return m_value; } 55 | } 56 | 57 | public override void Accept(IVisitor visitor) 58 | { 59 | visitor.VisitCase(this); 60 | } 61 | 62 | void INodeParent.Replace(CNode child, CNode newchild) 63 | { 64 | if (child == m_value) 65 | m_value = (CExpression)newchild; 66 | newchild.Parent = this; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /AST/CCast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CCast : CParenExpression 8 | { 9 | public CCast(CTypeRef type, CExpression exp) 10 | : base(type.TypeName, exp) 11 | { 12 | LoadType(type); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /AST/CCatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CCatch : CStatement 8 | { 9 | CVariable pivot; 10 | CStatementBlock statements = new CStatementBlock(); 11 | 12 | public CVariable Pivot 13 | { 14 | get { return pivot; } 15 | set { pivot = value; } 16 | } 17 | 18 | public CStatementBlock Statements 19 | { 20 | get { return statements; } 21 | } 22 | 23 | public CCatch(CToken tok) 24 | : base(tok) { } 25 | 26 | public override void Accept(IVisitor visitor) 27 | { 28 | visitor.VisitCatch(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /AST/CClassConst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FogCreek.Wasabi.AST 4 | { 5 | public class CClassConst : CMember 6 | { 7 | CClass declaringClass; 8 | CConst myConst; 9 | public CClassConst(CClass declaringClass, CConst myConst) 10 | : base(myConst.Token, myConst.Name.Value, "const", 1, false) 11 | { 12 | this.declaringClass = declaringClass; 13 | this.myConst = myConst; 14 | Declared[0] = myConst; 15 | myConst.ClassConst = this; 16 | } 17 | 18 | public CConst Constant 19 | { 20 | get { return myConst; } 21 | } 22 | 23 | public override TokenTypes Visibility 24 | { 25 | get { return TokenTypes.visPublic; } 26 | } 27 | 28 | public override CClass DeclaringClass 29 | { 30 | get { return declaringClass; } 31 | } 32 | 33 | public override bool SemanticallyComplete 34 | { 35 | get { return myConst.SemanticallyComplete; } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /AST/CComment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | 7 | public class CComment : CStatement 8 | { 9 | private String commentString; 10 | 11 | public CComment(CToken token, String com) 12 | : base(token) 13 | { 14 | commentString = com; 15 | } 16 | 17 | public string Text 18 | { 19 | get { return commentString; } 20 | } 21 | 22 | public override void Accept(IVisitor visitor) 23 | { 24 | visitor.VisitComment(this); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /AST/CComparison.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CComparison : CBinaryOperator 7 | { 8 | public CComparison(CToken tok, CExpression lhs, CExpression rhs) 9 | : base(tok, lhs, rhs) 10 | { 11 | base.LoadType(BuiltIns.Boolean); 12 | } 13 | 14 | public override void Accept(IVisitor visit) 15 | { 16 | visit.VisitComparison(this); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /AST/CConcat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | 7 | public class CConcat : CBinaryOperator 8 | { 9 | public CConcat(CToken tok, CExpression lhs, CExpression rhs) 10 | : base(tok, lhs, rhs) 11 | { 12 | } 13 | 14 | private delegate bool fIsConst(object o); 15 | 16 | public override bool IsConstant 17 | { 18 | get 19 | { 20 | CClass __string = BuiltIns.String; 21 | fIsConst isConst = delegate(object o) 22 | { 23 | if (o is CConstantExpression) 24 | return ((CConstantExpression)o).Type == __string; 25 | if (o is CConcat) 26 | return ((CConcat)o).IsConstant; 27 | return false; 28 | }; 29 | return isConst(Left) && isConst(Right); 30 | } 31 | } 32 | 33 | private delegate string fGetConst(object o); 34 | 35 | public string ConstantValue 36 | { 37 | get 38 | { 39 | if (!IsConstant) 40 | throw new InvalidOperationException("Not a constant node"); 41 | fGetConst getConst = delegate(object o) 42 | { 43 | if (o is CConstantExpression) 44 | return ((CConstantExpression)o).Value.Value; 45 | if (o is CConcat) 46 | return ((CConcat)o).ConstantValue; 47 | throw new InvalidOperationException("Not a constant node"); 48 | }; 49 | return getConst(Left) + getConst(Right); 50 | } 51 | } 52 | 53 | public override void Accept(IVisitor visitor) 54 | { 55 | visitor.VisitConcat(this); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /AST/CConst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | 7 | // this class is for statements in vbscript that define constants 8 | public class CConst : CStatement, INodeParent, IAttributed, IVariable 9 | { 10 | private CToken constName; 11 | private CExpression constValue; 12 | 13 | public CConst(CToken token, CToken name, CExpression exp) 14 | : base(token) 15 | { 16 | constName = name; 17 | constValue = exp; 18 | constValue.Parent = this; 19 | } 20 | 21 | public CToken Name 22 | { 23 | get { return constName; } 24 | } 25 | 26 | public CExpression Value 27 | { 28 | get { return constValue; } 29 | } 30 | 31 | void INodeParent.Replace(CNode child, CNode newchild) 32 | { 33 | if (child == constValue) 34 | constValue = (CExpression)newchild; 35 | newchild.Parent = this; 36 | } 37 | 38 | public override void Accept(IVisitor visitor) 39 | { 40 | visitor.VisitConst(this); 41 | } 42 | 43 | private CClassConst ccc; 44 | public CClassConst ClassConst 45 | { 46 | get { return ccc; } 47 | set { ccc = value; } 48 | } 49 | 50 | #region IAttributed Members 51 | 52 | CAttributeList attributes = new CAttributeList(); 53 | public CAttributeList Attributes 54 | { 55 | get { return attributes; } 56 | } 57 | 58 | #endregion 59 | 60 | #region IVariable Members 61 | 62 | 63 | string IVariable.Name 64 | { 65 | get { return constName.Value; } 66 | } 67 | 68 | public bool IsArray 69 | { 70 | get { return false; } 71 | } 72 | 73 | public bool AccessedBeforeUsed 74 | { 75 | get { return false; } 76 | } 77 | 78 | public int AssignmentCount 79 | { 80 | get { return 1; } 81 | } 82 | 83 | int accesses; 84 | public int AccessCount 85 | { 86 | get { return accesses; } 87 | } 88 | 89 | public string RawName 90 | { 91 | get { return constName.RawValue; } 92 | } 93 | 94 | public void incAssignmentCount(CClass currentclass, CFunction currentfunction) 95 | { 96 | throw new Exception("Const variable is readonly"); 97 | } 98 | 99 | public void incAccessCount(CClass currentclass, CFunction currentfunction) 100 | { 101 | accesses++; 102 | } 103 | 104 | public bool canAssign(CClass currentclass, CFunction currentfunction) 105 | { 106 | return false; 107 | } 108 | 109 | public void SetExternallyReferenced() 110 | { 111 | throw new NotImplementedException(); 112 | } 113 | 114 | #endregion 115 | 116 | public CClass ContainingClass { get; set; } 117 | 118 | public CFunction ContainingFunction { get; set; } 119 | } 120 | } -------------------------------------------------------------------------------- /AST/CConstantExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CConstantExpression : CExpression 7 | { 8 | private CToken m_value; 9 | 10 | public CConstantExpression(CToken tok) 11 | : base(tok) 12 | { 13 | m_value = tok; 14 | CClass type = null; 15 | switch (tok.TokenType) 16 | { 17 | case TokenTypes.number: 18 | int i; 19 | if (Int32.TryParse(tok.Value, out i) || tok.Value.StartsWith("0x")) 20 | type = BuiltIns.Int32; 21 | else 22 | type = BuiltIns.Double; 23 | break; 24 | 25 | case TokenTypes.str: 26 | type = BuiltIns.String; 27 | break; 28 | 29 | case TokenTypes.character: 30 | type = BuiltIns.Character; 31 | break; 32 | 33 | case TokenTypes.pound: 34 | type = BuiltIns.Date; 35 | break; 36 | 37 | case TokenTypes.keyword: 38 | if (tok.Value == "true") 39 | type = BuiltIns.Boolean; 40 | else if (tok.Value == "false") 41 | type = BuiltIns.Boolean; 42 | else if (tok.Value == "nothing") 43 | type = BuiltIns.Nothing; 44 | else if (tok.Value == "dbnull") 45 | type = BuiltIns.DbNull; 46 | break; 47 | } 48 | if (type != null) 49 | base.LoadType(type); 50 | } 51 | 52 | public override bool IsConstant 53 | { 54 | get 55 | { 56 | return true; 57 | } 58 | } 59 | 60 | public CToken Value 61 | { 62 | get { return m_value; } 63 | } 64 | 65 | public override void Accept(IVisitor visit) 66 | { 67 | visit.VisitConstantExpression(this); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /AST/CDefaultAccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CDefaultAccess : CAccess, INodeParent 7 | { 8 | private CAccess m_targetAccess; 9 | private CParameters parameters; 10 | private bool realDefaultMethodCall = false; 11 | 12 | public CDefaultAccess(CToken tok, CAccess item, CParameters parameters) 13 | : base(tok, tok) 14 | { 15 | m_targetAccess = item; 16 | m_targetAccess.Parent = this; 17 | this.parameters = parameters; 18 | this.parameters.Parent = this; 19 | item.IsCallExplicit = true; 20 | IsRootAccess = false; 21 | } 22 | 23 | public CAccess TargetAccess 24 | { 25 | get { return m_targetAccess; } 26 | } 27 | 28 | public CParameters Parameters 29 | { 30 | get { return parameters; } 31 | } 32 | 33 | public override void Accept(IVisitor visit) 34 | { 35 | visit.VisitDefaultAccess(this); 36 | } 37 | 38 | void INodeParent.Replace(CNode child, CNode newchild) 39 | { 40 | if (child == m_targetAccess) 41 | m_targetAccess = (CAccess)newchild; 42 | newchild.Parent = this; 43 | m_targetAccess.IsCallExplicit = true; 44 | } 45 | 46 | public bool IsRealDefaultMethodCall 47 | { 48 | get { return realDefaultMethodCall; } 49 | set { realDefaultMethodCall = value; } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /AST/CDictionaryType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CDictionaryType : CArrayType 8 | { 9 | private bool generatingMembers; 10 | private bool generatedMembers; 11 | 12 | protected override string NamePrefix 13 | { 14 | get { return "Dictionary"; } 15 | } 16 | 17 | protected override string Open { get { return "{"; } } 18 | protected override string Close { get { return "}"; } } 19 | 20 | public override bool CanBeRedimed 21 | { 22 | get { return false; } 23 | } 24 | 25 | public static List Dictionaries = new List(); 26 | 27 | public CDictionaryType(CTypeRef type) 28 | : base(type, 1) 29 | { 30 | indexType.InternalLoad(BuiltIns.String); 31 | Dictionaries.Add(this); 32 | IsObject = true; 33 | } 34 | 35 | public override CTypeRef ItemType 36 | { 37 | get { return base.ItemType; } 38 | set 39 | { 40 | base.ItemType = value; 41 | 42 | if (value.Resolved && generatedMembers) 43 | UpdateMembers(); 44 | } 45 | } 46 | 47 | private Mono.Cecil.MethodDefinition FindMethod(string name) 48 | { 49 | foreach (Mono.Cecil.MethodDefinition method in CecilType.Methods) 50 | { 51 | if (method.Name == name) 52 | return method; 53 | } 54 | throw new ArgumentOutOfRangeException("name"); 55 | } 56 | 57 | private void UpdateMembers() 58 | { 59 | CMethod items = (CMethod)base.LookupMember("items"); 60 | ((CArrayType)items.Function.Type.ActualType).ItemType = ItemType; 61 | 62 | CMethod add = (CMethod)base.LookupMember("add"); 63 | add.Function.Arguments[1].LoadType(ItemType); 64 | 65 | CProperty item = (CProperty)base.LookupMember("item"); 66 | item.LoadType(ItemType); 67 | if (item.GetAccessor != null) 68 | item.GetAccessor.LoadType(ItemType); 69 | if (item.SetAccessor != null) 70 | item.SetAccessor.Arguments[1].LoadType(ItemType); 71 | } 72 | 73 | public override IEnumerable DirectMemberIterator 74 | { 75 | get 76 | { 77 | if (!generatingMembers) 78 | { 79 | GenerateAndResolveMembers(); 80 | } 81 | return base.DirectMemberIterator; 82 | } 83 | } 84 | 85 | public override void SetMember(string k, CMember v) 86 | { 87 | if (!generatingMembers) 88 | { 89 | GenerateAndResolveMembers(); 90 | } 91 | base.SetMember(k, v); 92 | } 93 | 94 | public override CMember LookupMember(string k) 95 | { 96 | if (!generatingMembers) 97 | { 98 | GenerateAndResolveMembers(); 99 | } 100 | return base.LookupMember(k); 101 | } 102 | 103 | private void TryItemTypeFixup() 104 | { 105 | CClass type; 106 | CMethod items = (CMethod)base.LookupMember("items"); 107 | 108 | type = ((CArrayType)items.Declared[CProperty.ixGet].Type).ItemType.ActualType; 109 | 110 | if (type == null) 111 | { 112 | CMethod add = (CMethod)base.LookupMember("add"); 113 | type = add.Function.Arguments[1].Type.ActualType; 114 | } 115 | 116 | if (type == null) 117 | { 118 | CProperty item = (CProperty)base.LookupMember("item"); 119 | type = item.Type.ActualType; 120 | if (type == null && item.GetAccessor != null) 121 | type = item.GetAccessor.Type.ActualType; 122 | if (type == null && item.SetAccessor != null) 123 | type = item.SetAccessor.Arguments[1].Type.ActualType; 124 | } 125 | 126 | if (type != null) 127 | ItemType = new CTypeRef(null, type); 128 | } 129 | 130 | public override bool canConvertTo(CClass klass) 131 | { 132 | if (klass.Name == "progid:scripting.dictionary") 133 | return true; 134 | return base.canConvertTo(klass); 135 | } 136 | 137 | public override CMember DefaultMember 138 | { 139 | get { return LookupMember("item"); } 140 | set { throw new NotImplementedException(); } 141 | } 142 | 143 | 144 | private void GenerateMembers() 145 | { 146 | generatingMembers = true; 147 | 148 | // 149 | 150 | CMethod items = (CMethod)LookupMember("items"); 151 | CClass type = new CArrayType(1); 152 | items.LoadType(type); 153 | items.Function.LoadType(type); 154 | 155 | base.Scope.Clear(); 156 | foreach (CMember member in InheritedMemberIterator) 157 | { 158 | base.Scope.add(member); 159 | } 160 | 161 | generatingMembers = false; 162 | generatedMembers = true; 163 | } 164 | 165 | public override void Accept(IVisitor visitor) 166 | { 167 | GenerateAndResolveMembers(); 168 | 169 | base.Accept(visitor); 170 | 171 | GenerateAndResolveMembers(); 172 | } 173 | 174 | public override CScope Scope 175 | { 176 | get 177 | { 178 | GenerateAndResolveMembers(); 179 | return base.Scope; 180 | } 181 | } 182 | 183 | private void GenerateAndResolveMembers() 184 | { 185 | if (!generatedMembers) 186 | { 187 | GenerateMembers(); 188 | if (ItemType.Resolved) 189 | UpdateMembers(); 190 | } 191 | else if (!ItemType.Resolved) 192 | TryItemTypeFixup(); 193 | } 194 | } 195 | } -------------------------------------------------------------------------------- /AST/CDim.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CDim : CStatement, IAttributed 7 | { 8 | private List variables = new List(); 9 | private bool inlineComment; 10 | 11 | public CDim(CToken token) 12 | : base(token) 13 | { 14 | } 15 | 16 | public List Variables 17 | { 18 | get { return variables; } 19 | } 20 | 21 | public CAttributeList Attributes 22 | { 23 | get { return variables[0].Attributes; } 24 | } 25 | 26 | public override void Accept(IVisitor visitor) 27 | { 28 | visitor.VisitDim(this); 29 | } 30 | 31 | public bool InlineComment 32 | { 33 | get { return inlineComment; } 34 | set { inlineComment = value; } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /AST/CDirective.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CDirective : CStatement 7 | { 8 | public CDirective(CToken token) 9 | : base(token) 10 | { 11 | } 12 | 13 | public override void Accept(IVisitor visitor) 14 | { 15 | visitor.VisitDirective(this); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /AST/CDo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CDo : CStatement, INodeParent 7 | { 8 | private CExpression condition; 9 | private CStatementBlock statements = new CStatementBlock(); 10 | private bool bUntil; 11 | private bool postcondition; 12 | 13 | public CDo(CToken token) 14 | : base(token) 15 | { 16 | } 17 | 18 | public CExpression Condition 19 | { 20 | get { return condition; } 21 | set 22 | { 23 | condition = value; 24 | condition.Parent = this; 25 | } 26 | } 27 | 28 | public override void Accept(IVisitor visitor) 29 | { 30 | visitor.VisitDo(this); 31 | } 32 | 33 | public CStatementBlock Statements 34 | { 35 | get { return statements; } 36 | set { statements = value; } 37 | } 38 | 39 | public bool IsDoUntil 40 | { 41 | get { return bUntil; } 42 | set { bUntil = value; } 43 | } 44 | 45 | public bool IsPostConditionLoop 46 | { 47 | get { return postcondition; } 48 | set { postcondition = value; } 49 | } 50 | 51 | void INodeParent.Replace(CNode child, CNode newchild) 52 | { 53 | if (child == condition) 54 | condition = (CExpression)newchild; 55 | newchild.Parent = this; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /AST/CEnum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Diagnostics; 5 | 6 | namespace FogCreek.Wasabi.AST 7 | { 8 | [DebuggerDisplay("Name: {RawName}")] 9 | public class CEnum : CClass 10 | { 11 | public CEnum(CToken tok, CToken name) 12 | : base(tok, name.RawValue, name.Value, CTypeRef.Empty) 13 | { 14 | IsObject = false; 15 | IsNumeric = true; 16 | } 17 | 18 | public override void Accept(IVisitor visitor) 19 | { 20 | visitor.VisitEnum(this); 21 | } 22 | 23 | internal override void AddInterface(CTypeRef interfaceref) 24 | { 25 | throw new InvalidOperationException("Enums can't have interfaces"); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /AST/CExit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | // the exit statement in vbscript 7 | public class CExit : CStatement 8 | { 9 | private bool subFlag; 10 | private bool funcFlag; 11 | private String exitWhat; 12 | 13 | public CExit(CToken token, String exitWhat) 14 | : base(token) 15 | { 16 | this.exitWhat = exitWhat; 17 | if (exitWhat == "function") 18 | funcFlag = true; 19 | else if (exitWhat == "sub") 20 | subFlag = true; 21 | } 22 | 23 | public override void Accept(IVisitor visitor) 24 | { 25 | visitor.VisitExit(this); 26 | } 27 | 28 | public bool IsExitSub 29 | { 30 | get { return subFlag; } 31 | set { subFlag = value; } 32 | } 33 | 34 | public bool IsExitFunction 35 | { 36 | get { return funcFlag; } 37 | set { funcFlag = value; } 38 | } 39 | 40 | public String ExitType 41 | { 42 | get { return exitWhat; } 43 | set { exitWhat = value; } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /AST/CExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public abstract class CExpression : CNode 7 | { 8 | private bool lhsAssignmentTarget; 9 | private bool rhsAssignmentSource; 10 | private bool passedByRef = false; 11 | private CArgument referencedArgument; 12 | 13 | public CExpression(CToken token) 14 | : base(token) 15 | { 16 | } 17 | 18 | public virtual bool IsConstant 19 | { 20 | get { return false; } 21 | } 22 | 23 | public bool IsPassedByRef 24 | { 25 | get { return passedByRef; } 26 | set { passedByRef = value; } 27 | } 28 | 29 | public bool LhsAssignmentTarget 30 | { 31 | get { return lhsAssignmentTarget; } 32 | set { lhsAssignmentTarget = value; } 33 | } 34 | 35 | public bool RhsAssignmentSource 36 | { 37 | get { return rhsAssignmentSource; } 38 | set { rhsAssignmentSource = value; } 39 | } 40 | 41 | public CArgument ReferencedArgument 42 | { 43 | get { return referencedArgument; } 44 | set { referencedArgument = value; } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /AST/CExpressionStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CExpressionStatement : CStatement, INodeParent 7 | { 8 | private CExpression exp; 9 | 10 | public CExpressionStatement(CExpression exp) 11 | : base(exp.Token) 12 | { 13 | this.exp = exp; 14 | exp.Parent = this; 15 | } 16 | 17 | public CExpression InnerExpression 18 | { 19 | get { return exp; } 20 | } 21 | 22 | public override void Accept(IVisitor visitor) 23 | { 24 | visitor.VisitStatement(this); 25 | } 26 | 27 | void INodeParent.Replace(CNode child, CNode newchild) 28 | { 29 | if (child == exp) 30 | exp = (CExpression)newchild; 31 | newchild.Parent = this; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /AST/CField.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CField : CMember 7 | { 8 | private CMemberVariable declaration; 9 | private CVariable variable; 10 | 11 | public CField(CVariable var, CMemberVariable declaration) 12 | : base(var.Token, var.Name.Value, "field", 1, false) 13 | { 14 | Declared[0] = var; 15 | variable = var; 16 | var.Field = this; 17 | this.declaration = declaration; 18 | } 19 | 20 | public CField(CField field, bool isUnionMember) 21 | : base(field.Token, field.Name, "field", 1, isUnionMember) 22 | { 23 | this.declaration = field.declaration; 24 | Declared[0] = this.variable = field.variable; 25 | } 26 | 27 | public override bool SemanticallyComplete 28 | { 29 | get { return declaration.SemanticallyComplete; } 30 | } 31 | 32 | public override TokenTypes Visibility 33 | { 34 | get { return declaration.Visibility; } 35 | } 36 | 37 | public override CClass DeclaringClass 38 | { 39 | get { return declaration.DeclaringClass; } 40 | } 41 | 42 | public CMemberVariable MemberDeclaration 43 | { 44 | get { return declaration; } 45 | set { declaration = value; } 46 | } 47 | 48 | public CVariable Variable 49 | { 50 | get { return variable; } 51 | set { variable = value; } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /AST/CFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CFile : CNode, IAttributed, INodeParent 7 | { 8 | private String filename; 9 | private readonly string fullPathToFile; 10 | private bool includedByExecuteAtCompilerFile = false; 11 | private CAttributeList attribs = new CAttributeList(); 12 | private CStatementBlock statements = new CStatementBlock(); 13 | private List lambdas = new List(); 14 | private List nameSpaceResolutionPrefixes = new List(); 15 | private Dictionary classNameAliases = new Dictionary(StringComparer.InvariantCultureIgnoreCase); 16 | 17 | public CFile(String filename, string fullPathToFile) 18 | { 19 | this.filename = filename; 20 | this.fullPathToFile = fullPathToFile; 21 | statements.Parent = this; 22 | } 23 | 24 | public string Filename 25 | { 26 | get { return filename; } 27 | } 28 | 29 | public CStatementBlock Statements 30 | { 31 | get { return statements; } 32 | } 33 | 34 | public CAttributeList Attributes 35 | { 36 | get { return attribs; } 37 | } 38 | 39 | public List Lambdas 40 | { 41 | get { return lambdas; } 42 | } 43 | 44 | public string FullPathToFile 45 | { 46 | get { return fullPathToFile; } 47 | } 48 | 49 | public bool IncludedByExecuteAtCompilerFile 50 | { 51 | get { return includedByExecuteAtCompilerFile; } 52 | set { includedByExecuteAtCompilerFile = value; } 53 | } 54 | 55 | public List NameSpaceResolutionPrefixes 56 | { 57 | get { return nameSpaceResolutionPrefixes; } 58 | } 59 | 60 | public Dictionary ClassNameAliases 61 | { 62 | get { return classNameAliases; } 63 | } 64 | 65 | public override void Accept(IVisitor visitor) 66 | { 67 | visitor.VisitFile(this); 68 | } 69 | 70 | public void Replace(CNode child, CNode newchild) 71 | { 72 | throw new NotImplementedException(); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /AST/CFinally.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CFinally : CStatement 8 | { 9 | CStatementBlock statements = new CStatementBlock(); 10 | 11 | public CStatementBlock Statements 12 | { 13 | get { return statements; } 14 | } 15 | 16 | public CFinally(CToken tok) 17 | : base(tok) 18 | { 19 | } 20 | 21 | public override void Accept(IVisitor visitor) 22 | { 23 | visitor.VisitFinally(this); 24 | } 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /AST/CFor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | // vbcscipt for loop statement 7 | public class CFor : CStatement, INodeParent 8 | { 9 | private CAccess forVariable; // like i, or j, or counter 10 | private CExpression init; // the initial value of the var 11 | private CExpression condition; // the final value of the var 12 | private CExpression step; // the expression to add to the var 13 | private CStatementBlock statements = new CStatementBlock(); 14 | 15 | public CFor(CToken token, CToken var) 16 | : base(token) 17 | { 18 | forVariable = new CAccess(var, var); 19 | forVariable.Parent = this; 20 | } 21 | 22 | public CExpression Initializer 23 | { 24 | get { return init; } 25 | set 26 | { 27 | init = value; 28 | init.Parent = this; 29 | } 30 | } 31 | 32 | public CExpression Terminator 33 | { 34 | get { return condition; } 35 | set 36 | { 37 | condition = value; 38 | condition.Parent = this; 39 | } 40 | } 41 | 42 | public CExpression Step 43 | { 44 | get { return step; } 45 | set 46 | { 47 | step = value; 48 | step.Parent = this; 49 | } 50 | } 51 | 52 | [Obsolete("Use ForVariable instead")] 53 | public string ForVariableName 54 | { 55 | get { return ForVariableToken.Value; } 56 | } 57 | 58 | [Obsolete("Use ForVariable instead")] 59 | public CToken ForVariableToken 60 | { 61 | get { return forVariable.Token; } 62 | } 63 | 64 | public CAccess ForVariable 65 | { 66 | get { return forVariable; } 67 | } 68 | 69 | public CStatementBlock Statements 70 | { 71 | get { return statements; } 72 | set { statements = value; } 73 | } 74 | 75 | public override void Accept(IVisitor visitor) 76 | { 77 | visitor.VisitFor(this); 78 | } 79 | 80 | void INodeParent.Replace(CNode child, CNode newchild) 81 | { 82 | if (child == init) 83 | init = (CExpression)newchild; 84 | if (child == condition) 85 | condition = (CExpression)newchild; 86 | if (child == step) 87 | step = (CExpression)newchild; 88 | newchild.Parent = this; 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /AST/CForEach.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CForEach : CStatement, INodeParent 7 | { 8 | private CAccess forVariable; 9 | private CExpression group; 10 | private CStatementBlock statements = new CStatementBlock(); 11 | 12 | public CForEach(CToken token, CToken var) 13 | : base(token) 14 | { 15 | forVariable = new CAccess(var, var); 16 | } 17 | 18 | public CExpression Enumerable 19 | { 20 | get { return group; } 21 | set 22 | { 23 | group = value; 24 | group.Parent = this; 25 | } 26 | } 27 | 28 | [Obsolete("Use ForVariable instead")] 29 | public string ForVariableName 30 | { 31 | get { return ForVariable.Token.Value; } 32 | } 33 | 34 | [Obsolete("Use ForVariable instead")] 35 | public CToken ForVariableToken 36 | { 37 | get { return forVariable.Token; } 38 | } 39 | 40 | public CAccess ForVariable 41 | { 42 | get { return forVariable; } 43 | } 44 | 45 | public CStatementBlock Statements 46 | { 47 | get { return statements; } 48 | set { statements = value; } 49 | } 50 | 51 | public override void Accept(IVisitor visitor) 52 | { 53 | visitor.VisitForEach(this); 54 | } 55 | 56 | void INodeParent.Replace(CNode child, CNode newchild) 57 | { 58 | if (child == group) 59 | group = (CExpression)newchild; 60 | newchild.Parent = this; 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /AST/CFunctionType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CFunctionType : CClass 7 | { 8 | private readonly CFunction target; 9 | private readonly bool declarationOnly; 10 | 11 | public CFunction Target 12 | { 13 | get { return target; } 14 | } 15 | 16 | public CFunctionType(CToken token, CFunction function, bool declarationOnly) 17 | : base(token, function.TypeSignature) 18 | { 19 | target = function; 20 | this.declarationOnly = declarationOnly; 21 | 22 | CMethod method = new CMethod(function); 23 | DefaultMember = method; 24 | 25 | function.TypeChanged += new EventHandler(function_TypeChanged); 26 | foreach (CArgument arg in function.Arguments) 27 | arg.TypeChanged += new EventHandler(function_TypeChanged); 28 | 29 | this.IsSealed = true; 30 | 31 | // we don't actually want people accessing the default method directly 32 | // we also don't want it to get visited through the type. 33 | // so we don't do this: Members.Add(function.Name, method); 34 | Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(null, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 35 | } 36 | 37 | private void function_TypeChanged(object sender, EventArgs e) 38 | { 39 | UpdateName(); 40 | OnTypeChanged(); 41 | } 42 | 43 | private void UpdateName() 44 | { 45 | string name = target.TypeSignature; 46 | NameToken = CToken.Identifer(NameToken, name, name); 47 | } 48 | 49 | public override bool canConvertTo(CClass klass) 50 | { 51 | CFunctionType target = klass as CFunctionType; 52 | if (target == null) return base.canConvertTo(klass); 53 | 54 | UpdateName(); 55 | target.UpdateName(); 56 | 57 | return Name == target.Name; 58 | } 59 | 60 | public static bool PossibleMatch(CFunctionType from, CFunctionType to) 61 | { 62 | if (from.Target.Arguments.Count != to.Target.Arguments.Count) 63 | return false; 64 | 65 | for (int i = 0; i < from.Target.Arguments.Count; i++) 66 | { 67 | if (from.Target.Arguments[i].Direction.Value != to.Target.Arguments[i].Direction.Value) 68 | return false; 69 | 70 | if (from.Target.Arguments[i].Type.Resolved && to.Target.Arguments[i].Type.Resolved 71 | && from.Target.Arguments[i].Type.ActualType != to.Target.Arguments[i].Type.ActualType) 72 | return false; 73 | } 74 | 75 | return true; 76 | } 77 | 78 | public override bool SemanticallyComplete 79 | { 80 | get 81 | { 82 | if (target.SemanticallyComplete && base.SemanticallyComplete) 83 | return true; 84 | 85 | if (!target.Type.Resolved) 86 | return false; 87 | foreach (CArgument arg in target.Arguments) 88 | if (!arg.Type.Resolved) 89 | return false; 90 | if (declarationOnly || target.Statements.SemanticallyComplete) 91 | { 92 | base.SetSemanticallyComplete(); 93 | return true; 94 | } 95 | 96 | return false; 97 | } 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /AST/CGlobalAccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CGlobalAccess : CAccess 7 | { 8 | public CGlobalAccess(CToken tok) 9 | : base(tok, tok) 10 | { 11 | } 12 | 13 | public override void Accept(IVisitor visit) 14 | { 15 | visit.VisitGlobalAccess(this); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /AST/CHtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CHtml : CStatement 7 | { 8 | private String htmlString; 9 | private String[] stringArray = null; 10 | 11 | public CHtml(CToken token, String html) 12 | : base(token) 13 | { 14 | htmlString = html; 15 | } 16 | 17 | public string[] HtmlLines 18 | { 19 | get { if (stringArray == null) stringArray = htmlString.Split('\n'); return stringArray; } 20 | set { stringArray = value; } 21 | } 22 | 23 | public override void Accept(IVisitor visitor) 24 | { 25 | visitor.VisitHtml(this); 26 | } 27 | 28 | public String HtmlString 29 | { 30 | get { return htmlString; } 31 | set { htmlString = value; } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /AST/CIf.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CIf : CStatement, INodeParent 7 | { 8 | private CExpression condition; 9 | private CStatementBlock thenStatements = new CStatementBlock(); 10 | private CStatementBlock elseStatements = new CStatementBlock(); 11 | private CStatementBlock elseIfBlocks = new CStatementBlock(); 12 | private bool oneLineFlag; 13 | private bool elseIfFlag; 14 | 15 | public CIf(CToken token, CExpression condition, bool oneLine, bool elseIf) 16 | : base(token) 17 | { 18 | this.condition = condition; 19 | condition.Parent = this; 20 | oneLineFlag = oneLine; 21 | elseIfFlag = elseIf; 22 | } 23 | 24 | public CExpression Condition 25 | { 26 | get { return condition; } 27 | } 28 | 29 | public CStatementBlock ThenStatements 30 | { 31 | get { return thenStatements; } 32 | } 33 | 34 | public CStatementBlock ElseStatements 35 | { 36 | get { return elseStatements; } 37 | } 38 | 39 | public CStatementBlock ElseIfBlocks 40 | { 41 | get { return elseIfBlocks; } 42 | } 43 | 44 | public bool IsOneLine 45 | { 46 | get { return oneLineFlag; } 47 | } 48 | 49 | public bool IsElseIf 50 | { 51 | get { return elseIfFlag; } 52 | } 53 | 54 | public override void Accept(IVisitor visitor) 55 | { 56 | visitor.VisitIf(this); 57 | } 58 | 59 | void INodeParent.Replace(CNode child, CNode newchild) 60 | { 61 | if (child == condition) 62 | condition = (CExpression)newchild; 63 | newchild.Parent = this; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /AST/CIgnore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CIgnore : CStatement 7 | { 8 | public CIgnore(CToken token) 9 | : base(token) 10 | { 11 | } 12 | 13 | public override void Accept(IVisitor visitor) 14 | { 15 | visitor.VisitStatement(this); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /AST/CInterface.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Diagnostics; 5 | 6 | namespace FogCreek.Wasabi.AST 7 | { 8 | [DebuggerDisplay("Name: {RawName}")] 9 | public class CInterface : CClass 10 | { 11 | 12 | List genericParameters = new List(); 13 | 14 | public CInterface(CToken tok, CToken name) : base(tok, name.RawValue, name.Value, CTypeRef.Empty) { } 15 | 16 | public List GenericParameters { get { return genericParameters; } } 17 | 18 | public override void Accept(IVisitor visitor) 19 | { 20 | visitor.VisitInterface(this); 21 | } 22 | 23 | public override CMember LookupMember(string k) 24 | { 25 | CMember baseMember = base.LookupMember(k); 26 | if (baseMember == null) 27 | { 28 | foreach (CInterface iface in this.Interfaces) 29 | { 30 | CMember lum = iface.LookupMember(k); 31 | if (lum != null) 32 | return lum; 33 | } 34 | } 35 | return baseMember; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /AST/CLambdaExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CLambdaExpression : CExpression 7 | { 8 | private static int lambdaCount = 0; 9 | 10 | private int lambdaId; 11 | private CLambdaFunction lambdaFunction; 12 | private CFunctionType lambdaType; 13 | 14 | public CLambdaExpression(CToken token) 15 | : base(token) 16 | { 17 | lambdaId = lambdaCount++; 18 | } 19 | 20 | public CLambdaFunction LambdaFunction 21 | { 22 | get { return lambdaFunction; } 23 | } 24 | 25 | public CFunctionType LambdaType 26 | { 27 | get { return lambdaType; } 28 | } 29 | 30 | public override void Accept(IVisitor visitor) 31 | { 32 | visitor.VisitLambdaExpression(this); 33 | } 34 | 35 | public override bool SemanticallyComplete 36 | { 37 | get { return lambdaType.SemanticallyComplete; } 38 | } 39 | 40 | internal CStatementBlock StartInitialize(CFunction containingFunction, CFile containingFile, CTypeRef tref, CArgumentList args) 41 | { 42 | if (lambdaFunction != null) 43 | throw new InvalidOperationException("Lambdas can only be initalized once"); 44 | 45 | CClass @class = null; 46 | string extra = ""; 47 | if (containingFunction != null) 48 | { 49 | @class = containingFunction.Class; 50 | extra += containingFunction.RawName; 51 | } 52 | 53 | lambdaFunction = 54 | new CLambdaFunction(Token, containingFunction, containingFile, "Lambda_" + extra + "_" + lambdaId, tref, args); 55 | base.LoadType(lambdaType = new CFunctionType(Token, lambdaFunction, false)); 56 | 57 | lambdaFunction.Class = @class; 58 | 59 | return lambdaFunction.Statements; 60 | } 61 | 62 | internal void FinishInitialize(CExpression cExpression) 63 | { 64 | CReturn @return = new CReturn(Token); 65 | @return.Expression = cExpression; 66 | 67 | lambdaFunction.Statements.Add(@return); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /AST/CLambdaFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CLambdaFunction : CFunction 7 | { 8 | private readonly CFunction containingFunction; 9 | private readonly CFile containingFile; 10 | private readonly List externalReferences = new List(); 11 | 12 | public CLambdaFunction(CToken token, CFunction containingFunction, CFile containingFile, String name, CTypeRef tref, 13 | CArgumentList args) 14 | : base(token, name, name, TokenTypes.visInternal, FunctionType.Function, args, tref) 15 | { 16 | this.containingFunction = containingFunction; 17 | this.containingFile = containingFile; 18 | if (this.containingFunction != null) 19 | this.containingFunction.Lambdas.Add(this); 20 | else 21 | this.containingFile.Lambdas.Add(this); 22 | CallCount++; 23 | Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(null, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 24 | } 25 | 26 | public CFunction ContainingFunction 27 | { 28 | get { return containingFunction; } 29 | } 30 | 31 | public CFile ContainingFile 32 | { 33 | get { return containingFile; } 34 | } 35 | 36 | /// 37 | /// The list of external references, that are not globals or fields 38 | /// 39 | public List ExternalReferences 40 | { 41 | get { return externalReferences; } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /AST/CLock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CLock : CStatement, INodeParent 8 | { 9 | private CExpression lockObj; 10 | private CStatementBlock statements = new CStatementBlock(); 11 | 12 | public CLock(CToken token, CExpression value) 13 | : base(token) 14 | { 15 | lockObj = value; 16 | value.Parent = this; 17 | } 18 | 19 | public CStatementBlock Statements 20 | { 21 | get { return statements; } 22 | } 23 | 24 | public CExpression Value 25 | { 26 | get { return lockObj; } 27 | } 28 | 29 | public override void Accept(IVisitor visitor) 30 | { 31 | visitor.VisitLock(this); 32 | } 33 | 34 | #region INodeParent Members 35 | 36 | void INodeParent.Replace(CNode child, CNode newchild) 37 | { 38 | if (lockObj == child) 39 | { 40 | lockObj = (CExpression)newchild; 41 | newchild.Parent = this; 42 | } 43 | } 44 | 45 | #endregion 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /AST/CLogic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CLogic : CBinaryOperator 7 | { 8 | public CLogic(CToken tok, CExpression lhs, CExpression rhs) 9 | : base(tok, lhs, rhs) 10 | { 11 | } 12 | 13 | public override void Accept(IVisitor visit) 14 | { 15 | visit.VisitLogic(this); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /AST/CMath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CMath : CBinaryOperator 7 | { 8 | public CMath(CToken tok, CExpression lhs, CExpression rhs) 9 | : base(tok, lhs, rhs) 10 | { 11 | } 12 | 13 | public override void Accept(IVisitor visit) 14 | { 15 | visit.VisitMath(this); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /AST/CMathUnary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CMathUnary : CUnaryOperator 7 | { 8 | public CMathUnary(CToken tok, CExpression rhs) 9 | : base(tok, rhs) 10 | { 11 | } 12 | 13 | public override bool IsConstant 14 | { 15 | get 16 | { 17 | return Operand.IsConstant; 18 | } 19 | } 20 | 21 | public override void Accept(IVisitor visit) 22 | { 23 | visit.VisitMathUnary(this); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /AST/CMember.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CMemberDictionary : CNode, IEnumerable> 8 | { 9 | private List> members = new List>(); 10 | private Dictionary memberDict = new Dictionary(); 11 | 12 | public int Count 13 | { 14 | get { return members.Count; } 15 | } 16 | 17 | public IEnumerable Values 18 | { 19 | get 20 | { 21 | // We iterate over our list of members to preserve order. 22 | foreach (KeyValuePair pair in members) 23 | { 24 | yield return pair.Value; 25 | } 26 | } 27 | } 28 | 29 | public override void Accept(IVisitor visitor) 30 | { 31 | throw new NotImplementedException(); 32 | } 33 | 34 | public bool ContainsKey(string name) 35 | { 36 | return memberDict.ContainsKey(name); 37 | } 38 | 39 | public CMember this[string name] 40 | { 41 | get 42 | { 43 | return memberDict[name]; 44 | } 45 | set 46 | { 47 | if (memberDict.ContainsKey(name)) 48 | { 49 | for (int ix = 0; ix < members.Count; ix++) 50 | { 51 | if (String.CompareOrdinal(members[ix].Key, name) == 0) 52 | { 53 | members[ix] = new KeyValuePair(name, value); 54 | memberDict[name] = value; 55 | return; 56 | } 57 | } 58 | } 59 | else 60 | { 61 | members.Add(new KeyValuePair(name, value)); 62 | memberDict[name] = value; 63 | } 64 | } 65 | } 66 | 67 | /// 68 | ///Returns an enumerator that iterates through the collection. 69 | /// 70 | /// 71 | /// 72 | ///A that can be used to iterate through the collection. 73 | /// 74 | ///1 75 | IEnumerator> IEnumerable>.GetEnumerator() 76 | { 77 | return members.GetEnumerator(); 78 | } 79 | 80 | /// 81 | ///Returns an enumerator that iterates through a collection. 82 | /// 83 | /// 84 | /// 85 | ///An object that can be used to iterate through the collection. 86 | /// 87 | ///2 88 | public IEnumerator GetEnumerator() 89 | { 90 | return members.GetEnumerator(); 91 | } 92 | 93 | public bool TryGetValue(string name, out CMember result) 94 | { 95 | return memberDict.TryGetValue(name, out result); 96 | } 97 | 98 | public void Clear() 99 | { 100 | members.Clear(); 101 | memberDict.Clear(); 102 | } 103 | } 104 | 105 | public abstract class CMember : CNode, IHasVisibility 106 | { 107 | private readonly String name; 108 | private readonly String memberType; 109 | private readonly CNode[] declared; 110 | private readonly bool isUnionMember; 111 | 112 | public CMember(CToken tok, string name, string memberType, int declaredSize, bool isUnionMember) 113 | : base(tok) 114 | { 115 | this.name = name; 116 | this.memberType = memberType; 117 | declared = new CNode[declaredSize]; 118 | this.isUnionMember = isUnionMember; 119 | } 120 | 121 | public abstract TokenTypes Visibility { get; } 122 | public abstract CClass DeclaringClass { get; } 123 | 124 | public string Name 125 | { 126 | get { return name; } 127 | } 128 | 129 | private string rawname = null; 130 | public string RawName 131 | { 132 | get 133 | { 134 | if (rawname != null) 135 | return rawname; 136 | 137 | switch (memberType) 138 | { 139 | case "method": 140 | rawname = ((CMethod)this).Function.RawName; 141 | break; 142 | case "property": 143 | rawname = ((CProperty)this).GetAccessor.RawName; 144 | break; 145 | case "field": 146 | rawname = ((CField)this).Variable.Name.RawValue; 147 | break; 148 | case "const": 149 | rawname = ((CClassConst)this).Constant.Name.RawValue; 150 | break; 151 | case "override": 152 | CMemberOverload cmo = (CMemberOverload)this; 153 | foreach (var x in cmo.Overloads) 154 | { 155 | if (rawname == null) 156 | rawname = x.RawName; 157 | else if (rawname != x.RawName) 158 | throw new NotImplementedException(memberType + " with " + rawname + " and " + x.RawName); 159 | } 160 | break; 161 | default: 162 | throw new InvalidOperationException(); 163 | } 164 | return rawname; 165 | } 166 | } 167 | 168 | public string MemberType 169 | { 170 | get { return memberType; } 171 | } 172 | 173 | public override void ClearType() 174 | { 175 | if (declared[0] != null) 176 | declared[0].ClearType(); 177 | } 178 | 179 | public override void LoadType(CClass type) 180 | { 181 | if (declared[0] != null) 182 | declared[0].LoadType(type); 183 | } 184 | 185 | public override void LoadType(CTypeRef tref) 186 | { 187 | if (declared[0] != null) 188 | declared[0].LoadType(tref); 189 | } 190 | 191 | public override CTypeRef Type 192 | { 193 | get 194 | { 195 | if (declared[0] == null) 196 | return new CTypeRef(this, (CClass)null); 197 | return declared[0].Type; 198 | } 199 | } 200 | 201 | public CNode[] Declared 202 | { 203 | get { return declared; } 204 | } 205 | 206 | public bool IsUnionMember { get { return isUnionMember; } } 207 | 208 | public override void Accept(IVisitor visitor) 209 | { 210 | foreach (CNode node in declared) 211 | { 212 | if (node != null) 213 | node.Accept(visitor); 214 | } 215 | } 216 | 217 | public override bool SemanticallyComplete 218 | { 219 | get 220 | { 221 | for (int i = 0; i < declared.Length; i++) 222 | { 223 | if (declared[i] != null && !declared[i].SemanticallyComplete) 224 | return false; 225 | } 226 | return true; 227 | } 228 | } 229 | 230 | public override void SetSemanticallyComplete() 231 | { 232 | throw new InvalidOperationException("Class members are dynamically semantically complete"); 233 | } 234 | 235 | bool hasExplicit = false; 236 | string strExplicit = "Error In Compiler"; 237 | internal bool HasExplicitInterface { get { return hasExplicit; } } 238 | internal string ExplicitInterfaceName 239 | { 240 | get 241 | { 242 | if (hasExplicit) 243 | return strExplicit; 244 | throw new InvalidOperationException(this.name + " does not have an explicit interface."); 245 | } 246 | } 247 | 248 | internal void SetExplicitInterface(string rawIfaceName) 249 | { 250 | hasExplicit = true; 251 | strExplicit = rawIfaceName; 252 | } 253 | 254 | bool isStatic = false; 255 | public bool IsStatic 256 | { 257 | get { return isStatic; } 258 | set { isStatic = value; } 259 | } 260 | 261 | public string VisibilityString 262 | { 263 | get 264 | { 265 | switch (Visibility) 266 | { 267 | default: 268 | case TokenTypes.visPrivate: 269 | return "Private"; 270 | case TokenTypes.visProtected: 271 | return "Protected"; 272 | case TokenTypes.visPublic: 273 | return "Public"; 274 | case TokenTypes.visInternal: 275 | return "Internal"; 276 | } 277 | } 278 | } 279 | 280 | public virtual IEnumerable Overloads 281 | { 282 | get 283 | { 284 | return null; 285 | } 286 | } 287 | } 288 | } -------------------------------------------------------------------------------- /AST/CMemberAccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CMemberAccess : CAccess, INodeParent 7 | { 8 | private CAccess _object; 9 | private CMember member; 10 | 11 | public CMemberAccess(CToken tok, CAccess objectSource, CToken item) 12 | : base(tok, item) 13 | { 14 | _object = objectSource; 15 | _object.Parent = this; 16 | _object.IsMemberSource = true; 17 | IsRootAccess = false; 18 | } 19 | 20 | public CAccess MemberSource 21 | { 22 | get { return _object; } 23 | } 24 | 25 | public CMember ReferencedMember 26 | { 27 | get { return member; } 28 | set { member = value; } 29 | } 30 | 31 | public override void Accept(IVisitor visit) 32 | { 33 | visit.VisitMemberAccess(this); 34 | } 35 | 36 | void INodeParent.Replace(CNode child, CNode newchild) 37 | { 38 | if (child == _object) 39 | _object = (CAccess)newchild; 40 | newchild.Parent = this; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /AST/CMemberOverload.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using FogCreek.Wasabi.AST; 5 | 6 | namespace FogCreek.Wasabi.AST 7 | { 8 | public class CMemberOverload : CMember 9 | { 10 | CClass owner; 11 | List overloads = new List(); 12 | 13 | public CMemberOverload(CToken tok, CClass owner, string name) 14 | : base(tok, name, "override", 0, false) 15 | { 16 | this.owner = owner; 17 | } 18 | 19 | public CMemberOverload(CMemberOverload field, bool isUnionMember) 20 | : base(field.Token, field.Name, "override", 0, isUnionMember) 21 | { 22 | this.owner = field.DeclaringClass; 23 | } 24 | 25 | public void Add(CMember member) 26 | { 27 | if (member is CMemberOverload) 28 | { 29 | foreach (CMember m in ((CMemberOverload)member).overloads) 30 | Add(m); 31 | } 32 | else 33 | overloads.Add(member); 34 | } 35 | 36 | public CClass Owner 37 | { 38 | get { return owner; } 39 | } 40 | 41 | public override IEnumerable Overloads 42 | { 43 | get 44 | { 45 | return overloads; 46 | } 47 | } 48 | 49 | public override TokenTypes Visibility 50 | { 51 | get 52 | { 53 | TokenTypes vis = overloads[0].Visibility; 54 | foreach (CMember m in overloads) 55 | if (m.Visibility != vis) 56 | throw new NotImplementedException("Mixed visibility in member overloads"); 57 | return vis; 58 | } 59 | } 60 | 61 | public override CClass DeclaringClass 62 | { 63 | get { return owner; } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /AST/CMemberVariable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CMemberVariable : CDim, IHasVisibility 7 | { 8 | private TokenTypes visibility; 9 | 10 | /// Creates a new instance of CMemberVariable 11 | // ppub = 0, priv =1 as defined in token types interface 12 | public CMemberVariable(CToken token, TokenTypes visibility) 13 | : base(token) 14 | { 15 | this.visibility = visibility; 16 | } 17 | 18 | public TokenTypes Visibility 19 | { 20 | get { return visibility; } 21 | internal set { visibility = value; } 22 | } 23 | 24 | public override void Accept(IVisitor visitor) 25 | { 26 | visitor.VisitMemberVariable(this); 27 | } 28 | 29 | #region IHasVisibility Members 30 | 31 | public CClass DeclaringClass 32 | { 33 | get { return this.Variables[0].ContainingClass; } 34 | } 35 | 36 | bool isStatic = false; 37 | public bool IsStatic 38 | { 39 | get { return isStatic; } 40 | set { isStatic = value; } 41 | } 42 | 43 | #endregion 44 | } 45 | } -------------------------------------------------------------------------------- /AST/CMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CMethod : CMember 7 | { 8 | private CFunction function; 9 | 10 | public CMethod(CFunction func) 11 | : base(func.Token, func.Name, "method", 1, false) 12 | { 13 | Declared[0] = func; 14 | function = func; 15 | } 16 | 17 | public CMethod(CMethod method, bool isUnionMember) 18 | : base(method.Token, method.Name, "method", 1, isUnionMember) 19 | { 20 | Declared[0] = function = method.function; 21 | } 22 | 23 | public CFunction Function 24 | { 25 | get { return function; } 26 | } 27 | 28 | /// 29 | /// Function is a reserved word in Wasabi, so we add an alias "FunctionObject". 30 | /// 31 | public CFunction FunctionObject 32 | { 33 | get { return function; } 34 | } 35 | 36 | public override TokenTypes Visibility 37 | { 38 | get { return function.Visibility; } 39 | } 40 | 41 | public override CClass DeclaringClass 42 | { 43 | get { return function.DeclaringClass; } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /AST/CNew.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CNew : CAccess 7 | { 8 | private CToken classname; 9 | private CParameters @params; 10 | 11 | public CNew(CToken tok, CToken classname, CParameters @params) 12 | : base(tok, classname) 13 | { 14 | this.classname = classname; 15 | this.@params = @params; 16 | this.@params.Parent = this; 17 | } 18 | 19 | public CParameters Parameters 20 | { 21 | get { return @params; } 22 | } 23 | 24 | public CToken ClassName 25 | { 26 | get { return classname; } 27 | } 28 | 29 | public override void Accept(IVisitor visit) 30 | { 31 | visit.VisitNew(this); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /AST/CNewline.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CNewline : CStatement 7 | { 8 | public CNewline(CToken token) 9 | : base(token) 10 | { 11 | } 12 | 13 | public override void Accept(IVisitor visitor) 14 | { 15 | visitor.VisitStatement(this); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /AST/CNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public interface INodeParent 8 | { 9 | void Replace(CNode child, CNode newchild); 10 | } 11 | 12 | public enum NodeStateMode 13 | { 14 | Initial, 15 | Server, 16 | Client, 17 | MaxStateValue 18 | } 19 | 20 | public abstract class CNode 21 | { 22 | private static List allNodes = new List(); 23 | private CToken token; 24 | private CTypeRef type; 25 | private INodeParent parent; 26 | private bool _semanticallyComplete = false; 27 | public event EventHandler TypeChanged; 28 | 29 | protected CNode(CToken token) 30 | { 31 | type = new CTypeRef(this); 32 | this.token = token; 33 | lock (allNodes) allNodes.Add(this); 34 | } 35 | 36 | protected CNode() 37 | { 38 | type = new CTypeRef(this); 39 | token = null; 40 | lock (allNodes) allNodes.Add(this); 41 | } 42 | 43 | public virtual int LineNumber 44 | { 45 | get 46 | { 47 | if (token != null) 48 | return token.LineNumber; 49 | return 0; 50 | } 51 | } 52 | 53 | public virtual bool SemanticallyComplete 54 | { 55 | get { return _semanticallyComplete; } 56 | } 57 | 58 | public CToken Token 59 | { 60 | get { return token; } 61 | } 62 | 63 | public virtual CTypeRef Type 64 | { 65 | get { return type; } 66 | } 67 | 68 | public virtual void ClearType() 69 | { 70 | type = new CTypeRef(this); 71 | } 72 | 73 | public virtual void LoadType(CClass type) 74 | { 75 | this.type.InternalLoad(type); 76 | } 77 | 78 | public virtual void LoadType(CTypeRef tref) 79 | { 80 | type.InternalLoad(tref); 81 | } 82 | 83 | internal void DoTypeChanged() 84 | { 85 | OnTypeChanged(); 86 | } 87 | 88 | protected void OnTypeChanged() 89 | { 90 | if (TypeChanged != null) TypeChanged(this, new EventArgs()); 91 | } 92 | 93 | public INodeParent Parent 94 | { 95 | get { return parent; } 96 | protected internal set { parent = value; } 97 | } 98 | 99 | public virtual void SetSemanticallyComplete() 100 | { 101 | if (!type.Resolved) 102 | throw new InvalidOperationException("Type must be resolved before calling SetSemanticallyComplete()"); 103 | _semanticallyComplete = true; 104 | } 105 | 106 | public abstract void Accept(IVisitor visitor); 107 | 108 | internal static void ClearSemanticallyCompleteOnAllNodes() 109 | { 110 | foreach (CNode node in allNodes) 111 | node._semanticallyComplete = false; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /AST/CNot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CNot : CUnaryOperator 7 | { 8 | public CNot(CToken tok, CExpression rhs) 9 | : base(tok, rhs) 10 | { 11 | base.LoadType(BuiltIns.Boolean); 12 | } 13 | 14 | public override void Accept(IVisitor visit) 15 | { 16 | visit.VisitNot(this); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /AST/COnError.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class COnError : CStatement 7 | { 8 | private CToken action; 9 | 10 | public COnError(CToken tok, CToken action) 11 | : base(tok) 12 | { 13 | this.action = action; 14 | } 15 | 16 | public override void Accept(IVisitor visit) 17 | { 18 | visit.VisitOnError(this); 19 | } 20 | 21 | public CToken Action 22 | { 23 | get { return action; } 24 | set { action = value; } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /AST/COnExit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class COnExit : COnError 8 | { 9 | CStatement statement; 10 | 11 | public COnExit(CToken tok, CToken action, CStatement statement) 12 | : base(tok, action) 13 | { 14 | this.statement = statement; 15 | } 16 | 17 | public override void Accept(IVisitor visit) 18 | { 19 | visit.VisitOnExit(this); 20 | } 21 | 22 | public CStatement Statement { get { return statement; } } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /AST/COption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class COption : CStatement 7 | { 8 | private CToken name; 9 | private CToken param; 10 | private CFile file; 11 | 12 | public COption(CToken tok, CToken name, CToken param) 13 | : base(tok) 14 | { 15 | this.name = name; 16 | this.param = param; 17 | } 18 | 19 | public CToken Name 20 | { 21 | get { return name; } 22 | } 23 | 24 | public CToken Parameter 25 | { 26 | get { return param; } 27 | } 28 | 29 | public CFile File 30 | { 31 | get { return file; } 32 | set { file = value; } 33 | } 34 | 35 | public override void Accept(IVisitor visitor) 36 | { 37 | visitor.VisitOption(this); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /AST/COptionalByRef.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class COptionalByRef : CExpression 8 | { 9 | public COptionalByRef(CToken tok) 10 | : base(tok) 11 | { 12 | this.IsPassedByRef = true; 13 | } 14 | 15 | public override void Accept(IVisitor visitor) 16 | { 17 | visitor.VisitOptionalByRef(this); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /AST/CParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CParameters : INodeParent 8 | { 9 | public class ParameterList : IEnumerable 10 | { 11 | private readonly INodeParent parent; 12 | private List items = new List(); 13 | 14 | public ParameterList(INodeParent parent) 15 | { 16 | this.parent = parent; 17 | } 18 | 19 | public ParameterList(INodeParent parent, ParameterList source) 20 | { 21 | this.parent = parent; 22 | items.AddRange(source.items); 23 | } 24 | 25 | public void Add(CNode parameter) 26 | { 27 | if (parameter != null) 28 | parameter.Parent = parent; 29 | items.Add(parameter); 30 | } 31 | 32 | public void RemoveAt(int ix) 33 | { 34 | items.RemoveAt(ix); 35 | } 36 | 37 | public int Count 38 | { 39 | get { return items.Count; } 40 | } 41 | 42 | public CNode this[int ix] 43 | { 44 | get { return items[ix]; } 45 | set 46 | { 47 | items[ix] = value; 48 | value.Parent = parent; 49 | } 50 | } 51 | 52 | public void Replace(CNode child, CNode newchild) 53 | { 54 | for (int ix = 0; ix < items.Count; ix++) 55 | { 56 | if (items[ix] == child) 57 | { 58 | items[ix] = newchild; 59 | newchild.Parent = parent; 60 | } 61 | } 62 | } 63 | 64 | internal void UpdateParents() 65 | { 66 | foreach (CNode node in items) 67 | if (node != null) 68 | node.Parent = parent; 69 | } 70 | 71 | #region IEnumerable Members 72 | 73 | IEnumerator IEnumerable.GetEnumerator() 74 | { 75 | return items.GetEnumerator(); 76 | } 77 | 78 | #endregion 79 | 80 | #region IEnumerable Members 81 | 82 | IEnumerator IEnumerable.GetEnumerator() 83 | { 84 | return items.GetEnumerator(); 85 | } 86 | 87 | #endregion 88 | } 89 | 90 | public class NamedParameterList : object, IEnumerable>, INodeParent 91 | { 92 | CParameters parent; 93 | int count = 0; 94 | KeyValuePair[] items; 95 | 96 | public NamedParameterList(CParameters parent, int size) 97 | { 98 | this.parent = parent; 99 | items = new KeyValuePair[size * 2]; 100 | count = 0; 101 | } 102 | 103 | public NamedParameterList(CParameters parent) 104 | : this(parent, 16) 105 | { 106 | } 107 | 108 | public NamedParameterList(CParameters parent, NamedParameterList src) 109 | : this(parent, src.count) 110 | { 111 | Array.Copy(src.items, items, src.count); 112 | count = src.count; 113 | } 114 | 115 | public CNode this[string key] 116 | { 117 | get 118 | { 119 | for (int i = 0; i < count; i++) 120 | { 121 | if (items[i].Key == key) return items[i].Value; 122 | } 123 | throw new ArgumentOutOfRangeException("key"); 124 | } 125 | } 126 | 127 | public KeyValuePair this[int ix] 128 | { 129 | get { return items[ix]; } 130 | } 131 | 132 | public int Count 133 | { 134 | get { return count; } 135 | } 136 | 137 | #region INodeParent Members 138 | 139 | public void Replace(CNode child, CNode newchild) 140 | { 141 | for (int i = 0; i < count; i++) 142 | { 143 | if (items[i].Value == child) 144 | { 145 | items[i] = new KeyValuePair(items[i].Key, newchild); 146 | newchild.Parent = parent; 147 | } 148 | } 149 | } 150 | 151 | #endregion 152 | 153 | #region IEnumerable> Members 154 | 155 | public IEnumerator> GetEnumerator() 156 | { 157 | for (int i = 0; i < count; i++) 158 | { 159 | yield return items[i]; 160 | } 161 | } 162 | 163 | #endregion 164 | 165 | #region IEnumerable Members 166 | 167 | IEnumerator IEnumerable.GetEnumerator() 168 | { 169 | for (int i = 0; i < count; i++) 170 | { 171 | yield return items[i]; 172 | } 173 | } 174 | 175 | #endregion 176 | 177 | internal bool ContainsKey(string p) 178 | { 179 | for (int i = 0; i < count; i++) 180 | { 181 | if (items[i].Key == p) return true; 182 | } 183 | return false; 184 | } 185 | 186 | internal void Add(string p, CExpression cExpression) 187 | { 188 | if (items.Length == count) 189 | Array.Resize(ref items, items.Length * 2); 190 | items[count++] = new KeyValuePair(p, cExpression); 191 | cExpression.Parent = parent; 192 | } 193 | } 194 | 195 | private ParameterList unnamedParams; 196 | private NamedParameterList namedParams; 197 | private bool _semanticallyComplete = false; 198 | private CNode parent; 199 | 200 | public CParameters() 201 | { 202 | namedParams = new NamedParameterList(this); 203 | unnamedParams = new ParameterList(this); 204 | } 205 | 206 | public CParameters(CParameters @params) 207 | { 208 | parent = @params.parent; 209 | unnamedParams = new ParameterList(this, @params.unnamedParams); 210 | namedParams = new NamedParameterList(this, @params.namedParams); 211 | } 212 | 213 | public CParameters(params CExpression[] exprs) 214 | : this() 215 | { 216 | foreach (CExpression node in exprs) 217 | { 218 | unnamedParams.Add(node); 219 | } 220 | } 221 | 222 | public void Accept(IVisitor visit) 223 | { 224 | visit.VisitParameters(this); 225 | } 226 | 227 | internal List GetDistinctNodes() 228 | { 229 | List list = new List(); 230 | foreach (CNode node in unnamedParams) 231 | if (node != null && !list.Contains(node)) 232 | list.Add(node); 233 | foreach (KeyValuePair pair in namedParams) 234 | if (pair.Value != null && !list.Contains(pair.Value)) 235 | list.Add(pair.Value); 236 | return list; 237 | } 238 | 239 | public bool SemanticallyComplete 240 | { 241 | get { return _semanticallyComplete; } 242 | } 243 | 244 | public ParameterList Unnamed 245 | { 246 | get { return unnamedParams; } 247 | } 248 | 249 | public NamedParameterList Named 250 | { 251 | get { return namedParams; } 252 | } 253 | 254 | public CNode this[int ix] 255 | { 256 | get { return unnamedParams[ix]; } 257 | } 258 | 259 | public CNode Parent 260 | { 261 | get { return parent; } 262 | set { parent = value; } 263 | } 264 | 265 | public void setSemanticallyComplete() 266 | { 267 | _semanticallyComplete = true; 268 | } 269 | 270 | public void resetSemanticallyComplete() 271 | { 272 | _semanticallyComplete = false; 273 | } 274 | 275 | public void Replace(CNode child, CNode newchild) 276 | { 277 | namedParams.Replace(child, newchild); 278 | unnamedParams.Replace(child, newchild); 279 | } 280 | } 281 | } -------------------------------------------------------------------------------- /AST/CParenExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CParenExpression : CExpression, INodeParent 7 | { 8 | private CExpression inner; 9 | 10 | public CParenExpression(CToken tok, CExpression inner) 11 | : base(tok) 12 | { 13 | this.inner = inner; 14 | inner.Parent = this; 15 | } 16 | 17 | public CExpression InnerExpression 18 | { 19 | get { return inner; } 20 | } 21 | 22 | public override bool IsConstant 23 | { 24 | get 25 | { 26 | return inner.IsConstant; 27 | } 28 | } 29 | 30 | public override void Accept(IVisitor visit) 31 | { 32 | visit.VisitParenExpression(this); 33 | } 34 | 35 | void INodeParent.Replace(CNode child, CNode newchild) 36 | { 37 | if (inner == child) 38 | inner = (CExpression)newchild; 39 | newchild.Parent = this; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /AST/CPictureOfExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CPictureOfExpression : CExpression, INodeParent 7 | { 8 | private CAccess access; 9 | 10 | public CPictureOfExpression(CToken tok, CAccess access) 11 | : base(tok) 12 | { 13 | this.access = access; 14 | this.access.Parent = this; 15 | } 16 | 17 | public override void Accept(IVisitor visitor) 18 | { 19 | visitor.VisitPictureOf(this); 20 | } 21 | 22 | public CAccess AccessTarget 23 | { 24 | get { return access; } 25 | set { access = value; } 26 | } 27 | 28 | #region INodeParent Members 29 | 30 | void INodeParent.Replace(CNode child, CNode newchild) 31 | { 32 | if (child == access) 33 | { 34 | access = (CAccess)newchild; 35 | newchild.Parent = this; 36 | } 37 | } 38 | 39 | #endregion 40 | } 41 | } -------------------------------------------------------------------------------- /AST/CProperty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CProperty : CMember 7 | { 8 | public const int ixGet = 0; 9 | public const int ixSet = 1; 10 | 11 | private CFunction m_get; 12 | private CFunction m_set; 13 | 14 | public CProperty(CToken token, string name) 15 | : base(token, name, "property", 3, false) 16 | { 17 | } 18 | 19 | public CProperty(CProperty property, bool isUnionMember) 20 | : base(property.Token, property.Name, "property", 3, isUnionMember) 21 | { 22 | Declared[ixGet] = m_get = property.m_get; 23 | Declared[ixSet] = m_set = property.m_set; 24 | } 25 | 26 | public CFunction GetAccessor 27 | { 28 | get { return m_get; } 29 | set 30 | { 31 | if (m_get != null) 32 | throw new InvalidCastException(); 33 | m_get = value; 34 | Declared[ixGet] = value; 35 | } 36 | } 37 | 38 | public CFunction SetAccessor 39 | { 40 | get { return m_set; } 41 | set 42 | { 43 | if (m_set != null) 44 | throw new InvalidCastException(); 45 | m_set = value; 46 | Declared[ixSet] = value; 47 | } 48 | } 49 | 50 | public override TokenTypes Visibility 51 | { 52 | get { return (GetAccessor ?? SetAccessor).Visibility; } 53 | } 54 | 55 | public override CClass DeclaringClass 56 | { 57 | get { return (GetAccessor ?? SetAccessor).DeclaringClass; } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /AST/CReDim.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CReDim : CDim 7 | { 8 | private bool bPreserve; 9 | 10 | public CReDim(CToken token, bool preserve) 11 | : base(token) 12 | { 13 | bPreserve = preserve; 14 | } 15 | 16 | public bool PreserveArrayContents 17 | { 18 | get { return bPreserve; } 19 | } 20 | 21 | public override void Accept(IVisitor visitor) 22 | { 23 | visitor.VisitReDim(this); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /AST/CReturn.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CReturn : CStatement, INodeParent 7 | { 8 | private CExpression expression; 9 | 10 | public CReturn(CToken token) 11 | : base(token) {} 12 | 13 | public CExpression Expression 14 | { 15 | get { return expression; } 16 | set 17 | { 18 | this.expression = value; 19 | value.Parent = this; 20 | } 21 | } 22 | 23 | public void Replace(CNode child, CNode newchild) 24 | { 25 | if (child == expression) 26 | Expression = (CExpression)newchild; 27 | } 28 | 29 | public override void Accept(IVisitor visitor) 30 | { 31 | visitor.VisitReturn(this); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /AST/CScope.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CScope 7 | { 8 | public CScope Parent 9 | { 10 | get { return parent; } 11 | set { parent = value; } 12 | } 13 | 14 | private Dictionary funcs = new Dictionary(StringComparer.Ordinal); 15 | private Dictionary nodes = new Dictionary(StringComparer.Ordinal); 16 | private CScope parent; 17 | 18 | public CScope() 19 | { 20 | } 21 | 22 | public CScope(CScope scope) 23 | { 24 | foreach (KeyValuePair pair in scope.funcs) 25 | { 26 | funcs[pair.Key] = pair.Value; 27 | } 28 | foreach (KeyValuePair pair in scope.nodes) 29 | { 30 | nodes[pair.Key] = pair.Value; 31 | } 32 | if (scope.parent != null) 33 | throw new InvalidOperationException("Cannot clone a parented scope"); 34 | } 35 | 36 | internal void add(String name, CNode node) 37 | { 38 | // TODO add previous existance check 39 | nodes[name] = node; 40 | } 41 | 42 | public void add(CConst var) 43 | { 44 | add(var.Name.Value, var); 45 | } 46 | 47 | public void add(CVariableBase var) 48 | { 49 | add(var.Name.Value, var); 50 | } 51 | 52 | public void add(CClass type) 53 | { 54 | add(type.Name, type); 55 | } 56 | 57 | public void add(CMember member) 58 | { 59 | if (member.MemberType == "field") 60 | add(member.Name, member.Declared[0]); 61 | else if (member.MemberType == "const") 62 | add(member.Name, member.Declared[0]); 63 | else 64 | funcs[member.Name] = member; 65 | } 66 | 67 | public void add(CFunction func) 68 | { 69 | if (func.Class == null) 70 | { 71 | funcs[func.Name] = func; 72 | funcs[func.FunctionAlias.ToLower()] = func; 73 | } 74 | switch (func.FunctionType) 75 | { 76 | case CFunction.vbPropertySet: 77 | case CFunction.vbSub: 78 | break; 79 | 80 | case CFunction.vbPropertyGet: 81 | case CFunction.vbFunction: 82 | default: 83 | func.scope.add(func.Name, func); 84 | break; 85 | } 86 | } 87 | 88 | public bool declared(String name) 89 | { 90 | if (local(name)) 91 | return true; 92 | if (parent != null) 93 | return parent.declared(name); 94 | return false; 95 | } 96 | 97 | public bool declaredFunction(String name) 98 | { 99 | if (localFunction(name)) 100 | return true; 101 | if (parent != null) 102 | return parent.declaredFunction(name); 103 | return false; 104 | } 105 | 106 | public bool local(String name) 107 | { 108 | return nodes.ContainsKey(name); 109 | } 110 | 111 | public bool localFunction(String name) 112 | { 113 | return funcs.ContainsKey(name); 114 | } 115 | 116 | public void setNode(String name, CNode node) 117 | { 118 | if (nodes.ContainsKey(name)) 119 | nodes[name] = node; 120 | else 121 | parent.setNode(name, node); 122 | } 123 | 124 | public CNode getNode(String name) 125 | { 126 | CNode nod; 127 | if (!nodes.TryGetValue(name, out nod)) 128 | return parent.getNode(name); 129 | return nod; 130 | } 131 | 132 | public CNode getFunction(String name) 133 | { 134 | CNode val; 135 | if (!funcs.TryGetValue(name, out val)) 136 | return parent.getFunction(name); 137 | return val; 138 | } 139 | 140 | internal void Clear() 141 | { 142 | funcs.Clear(); 143 | nodes.Clear(); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /AST/CSelect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | // the class for the switch(select) statement 7 | public class CSelect : CStatement, INodeParent 8 | { 9 | private CExpression pivot; // this is the variable that it swings on 10 | private CStatementBlock cases; // this will be a vector of case objects 11 | 12 | public CSelect(CToken token, CExpression pivot) 13 | : base(token) 14 | { 15 | cases = new CStatementBlock(); 16 | this.pivot = pivot; 17 | pivot.Parent = this; 18 | } 19 | 20 | public CExpression Pivot 21 | { 22 | get { return pivot; } 23 | } 24 | 25 | public CStatementBlock Cases 26 | { 27 | get { return cases; } 28 | } 29 | 30 | public override void Accept(IVisitor visitor) 31 | { 32 | visitor.VisitSelect(this); 33 | } 34 | 35 | void INodeParent.Replace(CNode child, CNode newchild) 36 | { 37 | if (child == pivot) 38 | pivot = (CExpression)newchild; 39 | newchild.Parent = this; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /AST/CSpecialEqual.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | // the CSpecialEqual class is for this situation <%=something%> which turns into <% Response.Write something %> 7 | public class CSpecialEqual : CStatement, INodeParent 8 | { 9 | private CExpression expr; 10 | 11 | public CSpecialEqual(CToken token, CExpression value) 12 | : base(token) 13 | { 14 | expr = value; 15 | expr.Parent = this; 16 | } 17 | 18 | public CExpression Value 19 | { 20 | get { if (expr.Parent != this) throw new DataMisalignedException(); return expr; } 21 | } 22 | 23 | public override void Accept(IVisitor visitor) 24 | { 25 | visitor.VisitSpecialEqual(this); 26 | } 27 | 28 | void INodeParent.Replace(CNode child, CNode newchild) 29 | { 30 | if (child == expr) 31 | expr = (CExpression)newchild; 32 | newchild.Parent = this; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /AST/CStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | // all of the other classes which handle the different kinds of statements in 7 | // the vbs language all inherit from this class 8 | public abstract class CStatement : CNode 9 | { 10 | private bool hasInlineComment = false; 11 | 12 | protected internal CStatement(CToken token) 13 | : base(token) 14 | { 15 | } 16 | 17 | public bool HasInlineComment 18 | { 19 | get { return hasInlineComment; } 20 | set { hasInlineComment = value; } 21 | } 22 | 23 | public abstract override void Accept(IVisitor visitor); 24 | } 25 | } -------------------------------------------------------------------------------- /AST/CStatementBlock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CStatementBlock : CNode, IEnumerable, INodeParent 8 | { 9 | private List m_statements = new List(); 10 | private bool suppressIndent = false; 11 | 12 | public CStatementBlock() 13 | { 14 | } 15 | 16 | public CStatementBlock(CToken tok, bool suppressIndent) : base(tok) 17 | { 18 | this.suppressIndent = suppressIndent; 19 | } 20 | 21 | public void Add(CNode node) 22 | { 23 | m_statements.Add(node); 24 | node.Parent = this; 25 | } 26 | 27 | public int Count 28 | { 29 | get { return m_statements.Count; } 30 | } 31 | 32 | public int IndexOf(CNode node) 33 | { 34 | if (node is CVariable) 35 | return IndexOf((CVariable)node); 36 | return m_statements.IndexOf(node); 37 | } 38 | 39 | private int IndexOf(CVariable var) 40 | { 41 | int ix = m_statements.IndexOf(var); 42 | if (ix >= 0) 43 | return ix; 44 | 45 | for (ix = 0; ix < m_statements.Count; ix++) 46 | { 47 | CNode n = m_statements[ix]; 48 | if (n is CMemberVariable) 49 | if (((CMemberVariable)n).Variables.Contains(var)) 50 | return ix; 51 | } 52 | 53 | return -1; 54 | } 55 | 56 | public CNode this[int ix] 57 | { 58 | get { return m_statements[ix]; } 59 | } 60 | 61 | public override void Accept(IVisitor visitor) 62 | { 63 | visitor.VisitBlock(this); 64 | } 65 | 66 | void INodeParent.Replace(CNode child, CNode newchild) 67 | { 68 | for (int i = 0; i < Count; i++) 69 | { 70 | if (this[i] == child) 71 | m_statements[i] = newchild; 72 | } 73 | newchild.Parent = this; 74 | } 75 | 76 | public bool SuppressIndent 77 | { 78 | get { return suppressIndent; } 79 | } 80 | 81 | IEnumerator IEnumerable.GetEnumerator() 82 | { 83 | return m_statements.GetEnumerator(); 84 | } 85 | 86 | /// 87 | ///Returns an enumerator that iterates through the collection. 88 | /// 89 | /// 90 | /// 91 | ///A that can be used to iterate through the collection. 92 | /// 93 | ///1 94 | IEnumerator IEnumerable.GetEnumerator() 95 | { 96 | return m_statements.GetEnumerator(); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /AST/CTernary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CTernary : CExpression, INodeParent 7 | { 8 | private CExpression cond, lhs, rhs; 9 | 10 | public CTernary(CToken tok, CExpression cond, CExpression lhs, CExpression rhs) 11 | : base(tok) 12 | { 13 | this.cond = cond; 14 | this.lhs = lhs; 15 | this.rhs = rhs; 16 | 17 | cond.Parent = this; 18 | lhs.Parent = this; 19 | rhs.Parent = this; 20 | } 21 | 22 | public override bool IsConstant 23 | { 24 | get 25 | { 26 | return cond.IsConstant && lhs.IsConstant && rhs.IsConstant; 27 | } 28 | } 29 | 30 | public CExpression Cond 31 | { 32 | get { return cond; } 33 | } 34 | 35 | public CExpression Left 36 | { 37 | get { return lhs; } 38 | } 39 | 40 | public CExpression Right 41 | { 42 | get { return rhs; } 43 | } 44 | 45 | void INodeParent.Replace(CNode child, CNode newchild) 46 | { 47 | if (cond == child) 48 | cond = (CExpression)newchild; 49 | if (lhs == child) 50 | lhs = (CExpression)newchild; 51 | if (rhs == child) 52 | rhs = (CExpression)newchild; 53 | newchild.Parent = this; 54 | } 55 | 56 | public override void Accept(IVisitor visit) 57 | { 58 | visit.VisitTernary(this); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /AST/CThisAccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CThisAccess : CAccess 7 | { 8 | public CThisAccess(CToken tok) 9 | : base(tok, tok) 10 | { 11 | } 12 | 13 | public override void Accept(IVisitor visit) 14 | { 15 | visit.VisitThisAccess(this); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /AST/CThrow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CThrow : CStatement, INodeParent 8 | { 9 | CExpression expression; 10 | 11 | public CExpression Expression 12 | { 13 | get { return expression; } 14 | set 15 | { 16 | this.expression = value; 17 | value.Parent = this; 18 | } 19 | } 20 | 21 | /// 22 | /// Create a new Throw statement 23 | /// 24 | /// The token defining the Throw 25 | /// The expression, if any, being thrown (may be null) 26 | public CThrow(CToken token) 27 | : base(token) { } 28 | 29 | public void Replace(CNode child, CNode newchild) 30 | { 31 | if (child == expression) 32 | Expression = (CExpression)newchild; 33 | } 34 | 35 | public override void Accept(IVisitor visitor) 36 | { 37 | visitor.VisitThrow(this); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /AST/CToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | [DebuggerDisplay("Location: {Filename}:{LineNumber}, Value: {Value}")] 8 | public class CToken : Object 9 | { 10 | private String filename; 11 | private int line; 12 | private int offset; 13 | private string fullLine; 14 | private TokenTypes type; 15 | private String m_value; 16 | private String rawvalue; 17 | private bool spacebefore; 18 | private int ix = -1; 19 | public Object AdditionalInfo; 20 | 21 | public CToken(string filename, int line, int offset, string fullLine, TokenTypes typ, string val, string rawval, bool hasspacebefore) 22 | { 23 | this.filename = filename; 24 | this.line = line; 25 | this.offset = offset; 26 | this.fullLine = fullLine; 27 | type = typ; 28 | m_value = val; 29 | rawvalue = rawval; 30 | spacebefore = hasspacebefore; 31 | } 32 | 33 | public CToken(String filename, TokenTypes typ, String val) 34 | : this(filename, 0, 0, "", typ, val, val, false) 35 | { 36 | } 37 | 38 | public CToken() 39 | { 40 | type = (TokenTypes)(-1); 41 | m_value = ""; 42 | } 43 | 44 | private readonly static CToken Empty = new CToken(); 45 | 46 | public static CToken Identifer(CToken @src, String ident) 47 | { 48 | if (src == null) src = Empty; 49 | return new CToken(src.filename, src.line, src.offset, src.fullLine, TokenTypes.identifier, ident.ToLower(), ident, true); 50 | } 51 | 52 | public static CToken Identifer(CToken @src, String ident, String rawIdent) 53 | { 54 | if (src == null) src = Empty; 55 | return new CToken(src.filename, src.line, src.offset, src.fullLine, TokenTypes.identifier, ident, rawIdent, true); 56 | } 57 | 58 | public static CToken Keyword(CToken @src, String keyword) 59 | { 60 | if (src == null) src = Empty; 61 | return new CToken(src.filename, src.line, src.offset, src.fullLine, TokenTypes.keyword, keyword.ToLower(), keyword, true); 62 | } 63 | 64 | internal static CToken String(CToken @src, string alias) 65 | { 66 | if (src == null) src = Empty; 67 | return new CToken(src.filename, src.line, src.offset, src.fullLine, TokenTypes.str, alias, alias, true); 68 | } 69 | 70 | public string Filename 71 | { 72 | get { return filename; } 73 | } 74 | 75 | public int LineNumber 76 | { 77 | get { return line; } 78 | } 79 | 80 | public int ByteOffset 81 | { 82 | get { return offset; } 83 | } 84 | 85 | public string FullLine 86 | { 87 | get { return fullLine; } 88 | } 89 | 90 | public TokenTypes TokenType 91 | { 92 | get { return type; } 93 | } 94 | 95 | public string Value 96 | { 97 | get { return m_value; } 98 | } 99 | 100 | public string RawValue 101 | { 102 | get 103 | { 104 | if (rawvalue == null) return m_value; 105 | return rawvalue; 106 | } 107 | } 108 | 109 | public bool HasSpaceBefore 110 | { 111 | get { return spacebefore; } 112 | } 113 | 114 | public int Index 115 | { 116 | get { return ix; } 117 | set { ix = value; } 118 | } 119 | 120 | public String ToDebugString() 121 | { 122 | return string.Format("Location: {0}:{1}, Value: {2}", Filename, LineNumber, Value); 123 | } 124 | 125 | public override String ToString() 126 | { 127 | return m_value; 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /AST/CTry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | public class CTry : CStatement 8 | { 9 | CStatementBlock statements = new CStatementBlock(); 10 | CStatementBlock catchBlocks = new CStatementBlock(); 11 | CFinally finallyBlock; 12 | 13 | public CStatementBlock Statements 14 | { 15 | get { return statements; } 16 | } 17 | 18 | public CStatementBlock CatchBlocks 19 | { 20 | get { return catchBlocks; } 21 | } 22 | 23 | public CFinally FinallyBlock 24 | { 25 | get { return finallyBlock; } 26 | set { finallyBlock = value; } 27 | } 28 | 29 | /// 30 | /// Create a new Try-Catch-Finally block. 31 | /// 32 | /// The token defining the Try 33 | public CTry(CToken token) 34 | : base(token) { } 35 | 36 | public override void Accept(IVisitor visitor) 37 | { 38 | visitor.VisitTry(this); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /AST/CTypeRef.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | 5 | namespace FogCreek.Wasabi.AST 6 | { 7 | [DebuggerDisplay("TypeName: {TypeName}, ActualType: {ActualType}")] 8 | public struct CTypeRef 9 | { 10 | private readonly CNode owner; 11 | private CToken name; 12 | private CClass type; 13 | 14 | public static readonly CTypeRef Empty = new CTypeRef(null); 15 | 16 | public CTypeRef(CNode owner) 17 | { 18 | this.owner = owner; 19 | name = null; 20 | type = null; 21 | } 22 | 23 | public CTypeRef(CNode owner, CClass type) 24 | : this(owner) 25 | { 26 | InternalLoad(type); 27 | } 28 | 29 | public CTypeRef(CNode owner, CToken name) 30 | : this(owner) 31 | { 32 | InternalLoad(name); 33 | } 34 | 35 | [Obsolete("Only used by generators")] 36 | public CTypeRef(CNode owner, string name) : this(owner) 37 | { 38 | InternalLoad(CToken.Identifer(null, name)); 39 | } 40 | 41 | public CTypeRef(CNode owner, CTypeRef tref) 42 | : this(owner) 43 | { 44 | InternalLoad(tref); 45 | } 46 | 47 | public CNode Owner 48 | { 49 | get { return owner; } 50 | } 51 | 52 | internal void InternalLoad(CTypeRef tref) 53 | { 54 | TypeName = tref.name; 55 | ActualType = tref.type; 56 | } 57 | 58 | internal void InternalLoad(CClass type) 59 | { 60 | ActualType = type; 61 | } 62 | 63 | internal void InternalLoad(CToken name) 64 | { 65 | TypeName = name; 66 | ActualType = null; 67 | } 68 | 69 | public CToken TypeName 70 | { 71 | get 72 | { 73 | if (Resolved) return type.NameToken; 74 | return name; 75 | } 76 | private set { name = value; } 77 | } 78 | 79 | public string RawName 80 | { 81 | get { return type.RawName; } 82 | } 83 | 84 | public bool Resolved 85 | { 86 | get { return type != null; } 87 | } 88 | 89 | public CClass ActualType 90 | { 91 | get { return type; } 92 | private set 93 | { 94 | if (type != value) 95 | { 96 | type = value; 97 | if (owner != null) owner.DoTypeChanged(); 98 | } 99 | } 100 | } 101 | 102 | public static implicit operator CClass(CTypeRef tref) 103 | { 104 | return tref.ActualType; 105 | } 106 | 107 | public override bool Equals(object obj) 108 | { 109 | return this == (CTypeRef)obj; 110 | } 111 | 112 | public bool Equals(CTypeRef obj) 113 | { 114 | return this == obj; 115 | } 116 | 117 | public static bool operator ==(CTypeRef l, CTypeRef r) 118 | { 119 | if (!l.Resolved || !r.Resolved) 120 | { 121 | // allow comparisons to Empty 122 | if (l.name == null || r.name == null) 123 | { 124 | if (l.Resolved || r.Resolved) 125 | return false; 126 | return l.name == r.name; 127 | } 128 | 129 | throw new InvalidOperationException("Cannot compare unresolved types"); 130 | } 131 | return l.ActualType == r.ActualType; 132 | } 133 | 134 | public static bool operator !=(CTypeRef l, CTypeRef r) 135 | { 136 | return !(l == r); 137 | } 138 | 139 | public override int GetHashCode() 140 | { 141 | if (this.Resolved) 142 | return this.ActualType.GetHashCode(); 143 | if (this.name != null) 144 | return this.name.GetHashCode(); 145 | return base.GetHashCode(); 146 | } 147 | } 148 | } -------------------------------------------------------------------------------- /AST/CUnaryOperator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public abstract class CUnaryOperator : CExpression, INodeParent 7 | { 8 | private CToken action; 9 | private CExpression rhs; 10 | 11 | public CUnaryOperator(CToken tok, CExpression rhs) 12 | : base(tok) 13 | { 14 | action = tok; 15 | this.rhs = rhs; 16 | rhs.Parent = this; 17 | } 18 | 19 | public CToken Operation 20 | { 21 | get { return action; } 22 | } 23 | 24 | public virtual CExpression Operand 25 | { 26 | get { return rhs; } 27 | } 28 | 29 | void INodeParent.Replace(CNode child, CNode newchild) 30 | { 31 | if (child == rhs) 32 | rhs = (CExpression)newchild; 33 | newchild.Parent = this; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /AST/CUnionClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CUnionType : CClass 7 | { 8 | private List types = new List(); 9 | private static int unnamedCount; 10 | 11 | public CUnionType(CToken token, String rawname, String name) 12 | : base(token, "__Unamed_Union" + unnamedCount++) 13 | { 14 | CProgram.Global.AddClass(base.Name, this); 15 | NameToken = CToken.Identifer(token, name, rawname); 16 | CProgram.Global.AddClass(base.Name, this); 17 | } 18 | 19 | public CUnionType(CToken token) 20 | : base(token, "__Unamed_Union" + unnamedCount++) 21 | { 22 | CProgram.Global.AddClass(base.Name, this); 23 | NameToken = CToken.Identifer(token, "", ""); 24 | IsObject = false; 25 | } 26 | 27 | [Obsolete("Use Add(CTypeRef tref) instead")] 28 | public virtual void Add(Object type) 29 | { 30 | Add(type, type as string); 31 | } 32 | 33 | [Obsolete("Use Add(CTypeRef tref) instead")] 34 | public virtual void Add(Object type, String rawTypeName) 35 | { 36 | if (type is CTypeRef) 37 | Add((CTypeRef)type); 38 | else if (type is CUnionType) 39 | Add((CUnionType)type); 40 | else if (type is CClass) 41 | Add((CClass)type); 42 | else 43 | Add((string)type, rawTypeName); 44 | } 45 | 46 | [Obsolete("Use Add(CTypeRef tref) instead")] 47 | public virtual void Add(CClass type) 48 | { 49 | Add(new CTypeRef(this, type)); 50 | } 51 | 52 | [Obsolete("Use Add(CTypeRef tref) instead")] 53 | public virtual void Add(String type, String rawtype) 54 | { 55 | Add(new CTypeRef(this, CToken.Identifer(null, type, rawtype))); 56 | } 57 | 58 | public virtual void Add(CTypeRef tref) 59 | { 60 | if (tref.Resolved && tref.ActualType is CUnionType) 61 | Add((CUnionType)tref.ActualType); 62 | else 63 | { 64 | string prefix = " Or "; 65 | if (Name == "") 66 | prefix = ""; 67 | NameToken = 68 | CToken.Identifer(NameToken, Name + prefix + tref.TypeName.Value, 69 | RawName + prefix + tref.TypeName.RawValue); 70 | types.Add(new CTypeRef(this, tref)); 71 | } 72 | } 73 | 74 | public virtual void Add(CUnionType union) 75 | { 76 | foreach (CTypeRef type in union.types) 77 | Add(type); 78 | } 79 | 80 | public override CAttributeList Attributes 81 | { 82 | get 83 | { 84 | CAttributeList cal = new CAttributeList(); 85 | cal.Add(base.Attributes); 86 | 87 | if (!types[0].Resolved) 88 | return cal; 89 | 90 | foreach (CAttribute at in types[0].ActualType.Attributes) 91 | { 92 | bool found = true; 93 | IEnumerator it = types.GetEnumerator(); 94 | it.MoveNext(); 95 | while (found && it.MoveNext()) 96 | { 97 | if (!it.Current.Resolved) 98 | found = false; 99 | else if (!it.Current.ActualType.Attributes.contains(at.Name)) 100 | found = false; 101 | } 102 | 103 | if (found) 104 | cal.Add(at.NameToken, at.Parameters, new CTypeRef(at, at.Type)); 105 | } 106 | 107 | return cal; 108 | } 109 | } 110 | 111 | public virtual String UpdateMembers(IVisitor checker) 112 | { 113 | if (types.Count == 0) 114 | return "Empty enum type used"; 115 | 116 | bool isObject = true; 117 | for (int i = 0; i < types.Count; i++) 118 | { 119 | CTypeRef otype = types[i]; 120 | if (!otype.Resolved) 121 | { 122 | CClass ntype = CProgram.Global.FindClass(otype.TypeName); 123 | if (ntype == null) 124 | return "Cannot find type " + otype.TypeName.RawValue; 125 | otype.InternalLoad(ntype); 126 | } 127 | types[i] = otype; 128 | types[i].ActualType.Accept(checker); 129 | isObject = isObject && otype.ActualType.IsObject; 130 | } 131 | IsObject = isObject; 132 | 133 | base.ClearMembers(); 134 | Scope.Clear(); 135 | 136 | foreach (CMember member in types[0].ActualType.InheritedMemberIterator) 137 | { 138 | bool found; 139 | if (member is CMemberOverload) 140 | found = false; 141 | else// Unions can only access public members 142 | found = member.Visibility == TokenTypes.visPublic; 143 | 144 | 145 | IEnumerator it = types.GetEnumerator(); 146 | it.MoveNext(); 147 | while (found && it.MoveNext()) 148 | { 149 | CClass type = it.Current.ActualType; 150 | CMember luMember = type.LookupMember(member.Name); 151 | if (luMember == null) 152 | found = false; 153 | else if (luMember.MemberType != member.MemberType) 154 | // one's a method, the other's a field, or etc... 155 | found = false; 156 | else if (luMember.Visibility != TokenTypes.visPublic) 157 | found = false; 158 | else 159 | { 160 | switch (luMember.MemberType) 161 | { 162 | case "method": 163 | CMethod metho = (CMethod)member; 164 | CMethod luMetho = (CMethod)luMember; 165 | // already checked return type, let's try the parameters 166 | if (metho.Function.Arguments.Count != luMetho.Function.Arguments.Count) 167 | found = false; 168 | break; 169 | case "property": 170 | found = UnionProperty((CProperty)member, (CProperty)luMember); 171 | // dur 172 | break; 173 | case "field": 174 | // already checked return type, nothing left to check 175 | break; 176 | case "override": 177 | found = false;// dur 178 | break; 179 | } 180 | } 181 | } 182 | if (found) 183 | { 184 | CMember fmember; 185 | switch (member.MemberType) 186 | { 187 | case "method": 188 | fmember = new CMethod((CMethod)member, true); 189 | break; 190 | case "property": 191 | fmember = new CProperty((CProperty)member, true); 192 | break; 193 | case "field": 194 | fmember = new CField((CField)member, true); 195 | break; 196 | case "override": 197 | fmember = new CMemberOverload((CMemberOverload)member, true); 198 | break; 199 | default: 200 | throw new InvalidOperationException(); 201 | } 202 | SetMember(member.Name, fmember); 203 | Scope.add(fmember); 204 | } 205 | } 206 | 207 | bool hasDefault = true; 208 | DefaultMember = null; 209 | foreach (CTypeRef _class in types) 210 | { 211 | var memberBase = ((CClass)types[0]).DefaultMember; 212 | var member = _class.ActualType.DefaultMember; 213 | if ( memberBase == null || 214 | member == null || 215 | !UnionProperty((CProperty)memberBase, (CProperty) member)) 216 | { 217 | hasDefault = false; 218 | break; 219 | } 220 | } 221 | if (hasDefault) 222 | DefaultMember = ((CClass)types[0]).DefaultMember; 223 | 224 | return null; 225 | } 226 | 227 | private static bool UnionProperty(CProperty propo, CProperty luPropo) 228 | { 229 | for (int i = 0; i < 3; i++) 230 | { 231 | if ((propo.Declared[i] == null) != (luPropo.Declared[i] == null)) 232 | return false; 233 | else if (propo.Declared[i] != null && 234 | ((CFunction)propo.Declared[i]).Arguments.Count != ((CFunction)luPropo.Declared[i]).Arguments.Count) 235 | return false; 236 | } 237 | return true; 238 | } 239 | 240 | public List Types 241 | { 242 | get { return types; } 243 | set { types = value; } 244 | } 245 | 246 | protected override bool canUnionConvert(CClass klass) 247 | { 248 | foreach (CTypeRef tref in types) 249 | { 250 | if (tref.ActualType == null || !tref.ActualType.canConvertTo(klass)) 251 | return false; 252 | } 253 | return true; 254 | } 255 | 256 | public override bool IsEnum 257 | { 258 | get 259 | { 260 | foreach (CTypeRef tref in types) 261 | { 262 | if (!tref.Resolved || !tref.ActualType.IsEnum) 263 | return false; 264 | } 265 | return true; 266 | } 267 | } 268 | 269 | public override bool IsInterface 270 | { 271 | get 272 | { 273 | foreach (CTypeRef tref in types) 274 | { 275 | if (!tref.Resolved || !tref.ActualType.IsInterface) 276 | return false; 277 | } 278 | return true; 279 | } 280 | } 281 | } 282 | } -------------------------------------------------------------------------------- /AST/CVariable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CVariable : CVariableBase, INodeParent 7 | { 8 | private CParameters arrayDimsinit; 9 | private CExpression init; 10 | private bool member; 11 | private CNode rootForRedim; 12 | private CField field; 13 | private CDim dim; 14 | private Mono.Cecil.FieldDefinition cecilField; 15 | private bool firstAccessIsRedimPreserve = false; 16 | 17 | public CVariable(CToken name, bool shared, CTypeRef tref, CParameters arrayDimsinit, CExpression init, CDim parent) 18 | : base(name, shared) 19 | { 20 | this.dim = parent; 21 | this.name = name; 22 | base.LoadType(tref); 23 | this.init = init; 24 | if (init != null) 25 | init.Parent = this; 26 | member = false; 27 | this.arrayDimsinit = arrayDimsinit; 28 | } 29 | 30 | public override void LoadType(CClass type) 31 | { 32 | base.LoadType(type); 33 | 34 | EnsureDiminsionInitializerIsValid(); 35 | } 36 | 37 | public override void LoadType(CTypeRef tref) 38 | { 39 | base.LoadType(tref); 40 | 41 | EnsureDiminsionInitializerIsValid(); 42 | } 43 | 44 | public bool FirstAccessIsRedimPreserve 45 | { 46 | get { return firstAccessIsRedimPreserve; } 47 | set { firstAccessIsRedimPreserve = value; } 48 | } 49 | 50 | public override bool IsField 51 | { 52 | get { return member; } 53 | set { member = value; } 54 | } 55 | 56 | 57 | public CDim Dim 58 | { 59 | get { return this.dim; } 60 | } 61 | 62 | public CNode RootForRedim 63 | { 64 | get { return rootForRedim; } 65 | set { rootForRedim = value; } 66 | } 67 | 68 | public CExpression Initializer 69 | { 70 | get { return init; } 71 | protected set 72 | { 73 | init = value; 74 | if (init != null) 75 | init.Parent = this; 76 | } 77 | } 78 | 79 | public CParameters DimensionInitializer 80 | { 81 | get { return arrayDimsinit; } 82 | } 83 | 84 | public override void Accept(IVisitor visitor) 85 | { 86 | visitor.VisitVariable(this); 87 | } 88 | 89 | public override void ConvertToArray(CClass type, int count) 90 | { 91 | base.ConvertToArray(type, count); 92 | 93 | EnsureDiminsionInitializerIsValid(); 94 | } 95 | 96 | private void EnsureDiminsionInitializerIsValid() 97 | { 98 | CDictionaryType dict = Type.ActualType as CDictionaryType; 99 | if (dict != null) 100 | return; 101 | 102 | CArrayType array = Type.ActualType as CArrayType; 103 | if (array == null || arrayDimsinit != null) 104 | return; 105 | 106 | int count = array.Dimensions; 107 | CParameters @params = new CParameters(); 108 | for (int i = 0; i < count; i++) 109 | @params.Unnamed.Add(null); 110 | 111 | arrayDimsinit = @params; 112 | } 113 | 114 | public Mono.Cecil.FieldDefinition CecilField 115 | { 116 | get { return cecilField; } 117 | set { cecilField = value; } 118 | } 119 | 120 | public CField Field 121 | { 122 | get { return field; } 123 | set { field = value; } 124 | } 125 | 126 | #region INodeParent Members 127 | 128 | void INodeParent.Replace(CNode child, CNode newchild) 129 | { 130 | if (child == Initializer) 131 | Initializer = (CExpression)newchild; 132 | } 133 | 134 | #endregion 135 | } 136 | } -------------------------------------------------------------------------------- /AST/CVariableBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public abstract class CVariableBase : CNode, IVariable, IAttributed 7 | { 8 | protected CVariableBase(CToken token, bool shared) 9 | : base(token) 10 | { 11 | this.shared = shared; 12 | } 13 | 14 | protected CVariableBase(CToken token) 15 | : this(token, false) 16 | { 17 | } 18 | 19 | protected CToken name; 20 | private CAttributeList attribs = new CAttributeList(); 21 | protected bool accessedBeforeUsed = false; 22 | protected int assignCount = 0; 23 | protected int accessCount = 0; 24 | private CClass containingClass; 25 | private CFunction containingFunction; 26 | private bool shared = false; 27 | private bool external = false; 28 | 29 | public virtual CToken Name 30 | { 31 | get { return name; } 32 | } 33 | 34 | String IVariable.Name 35 | { 36 | get { return name.Value; } 37 | } 38 | 39 | public CClass ContainingClass 40 | { 41 | get { return containingClass; } 42 | set { containingClass = value; } 43 | } 44 | 45 | public CFunction ContainingFunction 46 | { 47 | get { return containingFunction; } 48 | set { containingFunction = value; } 49 | } 50 | 51 | public virtual bool AccessedBeforeUsed 52 | { 53 | get { return accessedBeforeUsed; } 54 | } 55 | 56 | public virtual int AssignmentCount 57 | { 58 | get { return assignCount; } 59 | } 60 | 61 | public virtual int AccessCount 62 | { 63 | get { return accessCount; } 64 | } 65 | 66 | string IVariable.RawName 67 | { 68 | get { return name.RawValue; } 69 | } 70 | 71 | public bool IsArray 72 | { 73 | get { return Type.ActualType is CArrayType && !(Type.ActualType is CDictionaryType); } 74 | } 75 | 76 | public string TypeName 77 | { 78 | get 79 | { 80 | if (Type.TypeName != null) 81 | return Type.TypeName.Value; 82 | return null; 83 | } 84 | } 85 | 86 | public CAttributeList Attributes 87 | { 88 | get { return attribs; } 89 | } 90 | 91 | public abstract bool IsField { get; set; } 92 | 93 | public bool IsShared 94 | { 95 | get { return shared; } 96 | } 97 | 98 | public virtual void incAssignmentCount(CClass currentclass, CFunction currentfunction) 99 | { 100 | assignCount++; 101 | } 102 | 103 | public virtual void incAccessCount(CClass currentclass, CFunction currentfunction) 104 | { 105 | if (assignCount == 0) 106 | accessedBeforeUsed = true; 107 | accessCount++; 108 | } 109 | 110 | public virtual bool canAssign(CClass currentclass, CFunction currentfunction) 111 | { 112 | return true; 113 | } 114 | 115 | public virtual void ConvertToArray(CClass type, int count) 116 | { 117 | base.LoadType(type); 118 | } 119 | 120 | public bool IsExternallyReferenced 121 | { 122 | get { return external; } 123 | } 124 | 125 | public void SetExternallyReferenced() 126 | { 127 | external = true; 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /AST/CWhile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CWhile : CStatement, INodeParent 7 | { 8 | private CExpression condition; 9 | private CStatementBlock statements = new CStatementBlock(); 10 | 11 | public CWhile(CToken token, CExpression condition) 12 | : base(token) 13 | { 14 | this.condition = condition; 15 | this.condition.Parent = this; 16 | } 17 | 18 | public CExpression Condition 19 | { 20 | get { return condition; } 21 | } 22 | 23 | public CStatementBlock Statements 24 | { 25 | get { return statements; } 26 | } 27 | 28 | public override void Accept(IVisitor visitor) 29 | { 30 | visitor.VisitWhile(this); 31 | } 32 | 33 | void INodeParent.Replace(CNode child, CNode newchild) 34 | { 35 | if (child == condition) 36 | condition = (CExpression)newchild; 37 | newchild.Parent = this; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /AST/CWith.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CWith : CStatement, INodeParent 7 | { 8 | private CExpression withObj; 9 | private CStatementBlock statements = new CStatementBlock(); 10 | 11 | public CWith(CToken token, CExpression value) 12 | : base(token) 13 | { 14 | withObj = value; 15 | value.Parent = this; 16 | } 17 | 18 | public CStatementBlock Statements 19 | { 20 | get { return statements; } 21 | } 22 | 23 | public CExpression Value 24 | { 25 | get { return withObj; } 26 | } 27 | 28 | public override void Accept(IVisitor visitor) 29 | { 30 | visitor.VisitWith(this); 31 | } 32 | 33 | #region INodeParent Members 34 | 35 | void INodeParent.Replace(CNode child, CNode newchild) 36 | { 37 | if (withObj == child) 38 | { 39 | withObj = (CExpression)newchild; 40 | newchild.Parent = this; 41 | } 42 | } 43 | 44 | #endregion 45 | } 46 | } -------------------------------------------------------------------------------- /AST/CWithAccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public class CWithAccess : CAccess 7 | { 8 | public CWithAccess(CToken tok) 9 | : base(tok, tok) 10 | { 11 | } 12 | 13 | public override void Accept(IVisitor visit) 14 | { 15 | visit.VisitWithAccess(this); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /AST/IAttributed.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | internal interface IAttributed 7 | { 8 | CAttributeList Attributes { get; } 9 | } 10 | } -------------------------------------------------------------------------------- /AST/IHasVisibility.cs: -------------------------------------------------------------------------------- 1 | namespace FogCreek.Wasabi.AST 2 | { 3 | public interface IHasVisibility 4 | { 5 | CClass DeclaringClass { get; } 6 | TokenTypes Visibility { get; } 7 | bool IsStatic { get; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /AST/IVariable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | public interface IVariable 7 | { 8 | CToken Token { get; } 9 | String Name { get; } 10 | CTypeRef Type { get; } 11 | bool IsArray { get; } 12 | bool AccessedBeforeUsed { get; } 13 | int AssignmentCount { get; } 14 | int AccessCount { get; } 15 | 16 | string RawName { get; } 17 | 18 | void incAssignmentCount(CClass currentclass, CFunction currentfunction); 19 | void incAccessCount(CClass currentclass, CFunction currentfunction); 20 | bool canAssign(CClass currentclass, CFunction currentfunction); 21 | 22 | void SetExternallyReferenced(); 23 | } 24 | } -------------------------------------------------------------------------------- /AST/IVisitor.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace FogCreek.Wasabi.AST 3 | { 4 | public interface IVisitor 5 | { 6 | void VisitBlock(CStatementBlock statements); 7 | void VisitAssignment(CAssignment assign); 8 | void VisitCase(CCase ccase); 9 | void VisitClass(CClass cclas); 10 | void VisitComment(CComment comment); 11 | void VisitConcat(CConcat concat); 12 | void VisitConst(CConst cconst); 13 | void VisitDim(CDim dim); 14 | void VisitDo(CDo cdo); 15 | void VisitExit(CExit exit); 16 | void VisitReturn(CReturn _return); 17 | void VisitParenExpression(CParenExpression exp); 18 | void VisitFor(CFor cfor); 19 | void VisitForEach(CForEach _foreach); 20 | void VisitFunction(CFunction function); 21 | void VisitHtml(CHtml html); 22 | void VisitIf(CIf cif); 23 | void VisitMemberVariable(CMemberVariable membervariable); 24 | void VisitReDim(CReDim redim); 25 | void VisitSelect(CSelect select); 26 | void VisitSpecialEqual(CSpecialEqual specialequal); 27 | void VisitStatement(CStatement statement); 28 | void VisitToken(CToken token); 29 | void VisitWhile(CWhile cwhile); 30 | void VisitWith(CWith with); 31 | 32 | void VisitAccess(CAccess access); 33 | void VisitComparison(CComparison compare); 34 | void VisitConstantExpression(CConstantExpression constant); 35 | void VisitDefaultAccess(CDefaultAccess access); 36 | void VisitLogic(CLogic logic); 37 | void VisitMath(CMath math); 38 | void VisitMathUnary(CMathUnary math); 39 | void VisitMemberAccess(CMemberAccess access); 40 | void VisitNew(CNew _new); 41 | void VisitNot(CNot not); 42 | void VisitOnError(COnError onerror); 43 | void VisitParameters(CParameters parameters); 44 | void VisitThisAccess(CThisAccess access); 45 | void VisitWithAccess(CWithAccess access); 46 | void VisitTernary(CTernary ternary); 47 | 48 | void VisitVariable(CVariable var); 49 | void VisitPictureOf(CPictureOfExpression pic); 50 | void VisitOption(COption option); 51 | 52 | void VisitLambdaExpression(CLambdaExpression lambda); 53 | 54 | void VisitProgram(CProgram program); 55 | void VisitFile(CFile file); 56 | void VisitDirective(CDirective directive); 57 | 58 | void VisitInterface(CInterface iface); 59 | void VisitEnum(CEnum eration); 60 | 61 | void VisitTry(CTry _try); 62 | void VisitCatch(CCatch _catch); 63 | void VisitFinally(CFinally _finally); 64 | void VisitThrow(CThrow _throw); 65 | 66 | void VisitLock(CLock @lock); 67 | void VisitOnExit(COnExit onexit); 68 | void VisitBaseAccess(CBaseAccess _base); 69 | void VisitGlobalAccess(CGlobalAccess cGlobalAccess); 70 | void VisitOptionalByRef(COptionalByRef cOptionalByRef); 71 | void VisitAttribute(CAttribute cAttribute); 72 | } 73 | } -------------------------------------------------------------------------------- /AST/TokenTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FogCreek.Wasabi.AST 5 | { 6 | // this defines all the constants we use throughout thistle- not just token types 7 | public enum TokenTypes 8 | { 9 | maskPreserveCase = 0x10000000, 10 | maskTokenNumber = 0x000000FF, 11 | maskEscaped = 0x20000000, 12 | maskExpConnector = 0x40000000, 13 | maskPreprocDir = unchecked((int)0x80000000), 14 | maskVisibility = 0x01000000, 15 | 16 | // token types 17 | compareOp = 0x50000001, // <, <=, >, >=, <> 18 | str = 0x10000002, // "blah", strings 19 | character = 0x1000002b, // "c"c characters 20 | number = 0x00000003, // for now any int or double . . . 21 | comment = 0x10000004, // 'blah 22 | oParen = 0x50000005, // ( 23 | cParen = 0x50000006, // ) 24 | oCurly = 0x50000024, // { 25 | cCurly = 0x50000025, // } 26 | html = 0x10000007, // some html blocks 27 | arithOp = 0x50000008, // +,-,*,/ 28 | strConcat = 0x50000009, // the & 29 | dot = 0x5000000A, // . 30 | colon = 0x1000000B, // : 31 | newline = 0x1000000C, // the newline char (need to make : into newline) 32 | space = 0x1000000D, // this is for whitespace 33 | equal = 0x5000000E, // = 34 | comma = 0x5000000F, // commas seperate parameters etc 35 | underscore = 0x10000010, // imp for rolling over lines 36 | pound = 0x00000011, // # sign. used for dates 37 | aspDirective = 0x00000023, // ASP directive @ 38 | questionMark = 0x5000002b, // ternary conditional operator 39 | 40 | // identifier like tokens 41 | keyword = 0x00000014, // empty, false, nothing, dbnull, true 42 | vbFunc = 0x00000015, // some vb function like Cstr 43 | declaration = 0x00000016, // Class, Const, Dim, ReDim, Function, Sub . . . 44 | assignment = 0x00000017, // set 45 | controlFlow = 0x00000018, // if, then, else . . . 46 | conjunction = 0x4000001A, // and, or, not 47 | call = 0x0000001B, // Call 48 | me = 0x0000001C, // this, me 49 | identifier = 0x0000001D, // any word thats not a keyword (like a var or func) 50 | visPublic = 0x0100001E, 51 | visPrivate = 0x0100001F, 52 | visProtected = 0x01000029, 53 | visInternal = 0x0100002a, 54 | 55 | AspStart = unchecked((int)0x80000020), 56 | XxxEnd = unchecked((int)0x80000022), 57 | PreprocessorIf = unchecked((int)0x80000026), 58 | PreprocessorEndIf = unchecked((int)0x80000027), 59 | PreprocessorElse = unchecked((int)0x80000028), 60 | 61 | EOF = 0x000FFFF, // the end of a file 62 | EMPTY = 0, // used to for an invalid value; 63 | LastToken = 0x0000002c, 64 | } 65 | 66 | public static class TokenStrings 67 | { 68 | // specific words to look for that have special meaning. 69 | // within the list of the 'vbfuncs' are also functions that we have 70 | public static readonly String keywords = 71 | "false|nothing|dbnull|true|byref|byval|erase|preserve|on|pictureof|optional|shared|paramarray"; 72 | 73 | public static readonly String declarations = 74 | "abstract|class|const|dim|redim|function|sub|lambda|option|property|default|union|inherits|implements|overridable|override|interface|sealed|enum|static"; 75 | 76 | public static readonly String assignments = "set"; 77 | public static readonly String callStatement = "call"; 78 | public static readonly String meObject = "me|this|base|global"; 79 | 80 | public static readonly String controlFlows = 81 | "do|until|in|select|case|while|loop|for|to|else|next|exit|each|wend|if|then|with|elseif|end|resume|goto|step|try|catch|finally|throw|return"; 82 | 83 | public static readonly String vbFuncs = 84 | "getarray|setarray|getfieldsize|setlocale|isempty|getlocale|rnd|sizeofmatches|getmatchat|getsubmatchat|getappvar|setappvar|formatnumber|dateserial|dateadd|datediff|cdate|isdate|formatdatetime|date|hour|minute|second|now|year|month|day|weekday|getAppVar|setAppVar|cbyte|instrrev|instr|string|now|replace|array|lbound|ubound|right|split|trim|ltrim|rtrim|clng|cint|cstr|isnumeric|strcomp|len|lenb|left|isdbnull|mid|cdbl|lcase|typename|round|asc|ascw|chr|chrw|int|cbool|hex|ucase|sqr|isarray|isobject|abs|log|exp|space|join|strreverse|getref|timevalue|randomize|timer"; 85 | 86 | public static readonly String conjunctions = "and|or|not|imp|xor|eqv"; 87 | public static readonly String arithOpWords = "mod"; 88 | 89 | public static string ToString(TokenTypes type) 90 | { 91 | switch (type) 92 | { 93 | case TokenTypes.oParen: return "'('"; 94 | case TokenTypes.cParen: return "')'"; 95 | case TokenTypes.oCurly: return "'{'"; 96 | case TokenTypes.cCurly: return "'}'"; 97 | } 98 | return type.ToString(); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /BuiltIns.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using FogCreek.Wasabi.AST; 5 | 6 | namespace FogCreek.Wasabi 7 | { 8 | public static class BuiltIns 9 | { 10 | public static readonly CClass Byte; 11 | public static readonly CClass Int32; 12 | public static readonly CClass Int64; 13 | public static readonly CClass Character; 14 | public static readonly CClass String; 15 | public static readonly CClass Boolean; 16 | public static readonly CClass Date; 17 | public static readonly CClass Double; 18 | public static readonly CClass Object; 19 | public static readonly CClass Variant; 20 | public static readonly CClass DbNull; 21 | public static readonly CClass Nothing; 22 | public static readonly CClass Void; 23 | public static readonly CClass FunctionPlaceHolder; 24 | public static readonly CClass SubPlaceHolder; 25 | 26 | public static readonly CFunction Array; 27 | public static readonly CFunction Dictionary; 28 | public static readonly CFunction GetRef; 29 | 30 | public static readonly CClass SystemArray; 31 | 32 | static BuiltIns() 33 | { 34 | /* These aren't fully resolved; we need to use Cecil to load the appropriate .NET type defitinions in. 35 | See ClrImporter.LoadBuiltins. */ 36 | Variant = new CClass("__Variant", null); 37 | Byte = new CClass("Byte", false); 38 | String = new CClass("String", true); 39 | Int32 = new CClass("Int32", true); 40 | Int64 = new CClass("Int64", true); 41 | Character = new CClass("Character", false); 42 | Boolean = new CClass("Boolean", true); 43 | Date = new CClass("Date", true); 44 | Double = new CClass("Double", true); 45 | Object = Variant; 46 | DbNull = new CClass("DbNull", false); 47 | Nothing = new CClass("Nothing", false); 48 | Nothing.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(null, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 49 | Void = new CClass("__Void", false); 50 | FunctionPlaceHolder = new CClass("__FunctionPlaceHolder", false); 51 | FunctionPlaceHolder.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(null, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 52 | SubPlaceHolder = new CClass("__SubPlaceHolder", false); 53 | SubPlaceHolder.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(null, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 54 | 55 | SetupGlobalTypes(); 56 | 57 | CArgumentList arrArgs = new CArgumentList(); 58 | arrArgs.Add(new CArgument(CToken.Keyword(null, "byval"), 59 | CToken.Identifer(null, "arglist"), 60 | new CTypeRef(null, Variant))); 61 | Array = new CFunction(CToken.Identifer(null, "Array"), "Array", "array", TokenTypes.visPublic, FunctionType.Function, 62 | arrArgs, new CTypeRef(null, new CArrayType(new CTypeRef(null, Variant), 1))); 63 | Array.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(null, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 64 | 65 | CArgumentList dicArgs = new CArgumentList(); 66 | dicArgs.Add(new CArgument(CToken.Keyword(null, "byval"), 67 | CToken.Identifer(null, "arglist"), 68 | new CTypeRef(null, Variant))); 69 | Dictionary = new CFunction(CToken.Identifer(null, "Dictionary"), "Dictionary", "dictionary", TokenTypes.visPublic, FunctionType.Function, 70 | dicArgs, new CTypeRef(null, new CDictionaryType(new CTypeRef(null, Variant)))); 71 | Dictionary.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(null, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 72 | 73 | CArgumentList refArgs = new CArgumentList(); 74 | refArgs.Add(new CArgument(CToken.Keyword(null, "byval"), 75 | CToken.Identifer(null, "func"), 76 | new CTypeRef(null, BuiltIns.String))); 77 | GetRef = new CFunction(CToken.Identifer(null, "GetRef"), "GetRef", "getref", TokenTypes.visPublic, FunctionType.Function, refArgs, 78 | new CTypeRef(null, BuiltIns.FunctionPlaceHolder)); 79 | GetRef.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(null, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 80 | 81 | // add string ienumerator interface 82 | CToken ifaceName = CToken.Identifer(null, "System.Collections.Generic.IEnumerable`1"); 83 | CInterface iface = new CInterface(ifaceName, ifaceName); 84 | iface.GenericParameters.Add(Character); 85 | String.AddInterface(new CTypeRef(null, iface)); 86 | } 87 | 88 | private static void SetupGlobalTypes() 89 | { 90 | Byte.IsNumeric = Int32.IsNumeric = Double.IsNumeric = Date.IsNumeric = Int64.IsNumeric = true; 91 | Character.IsObject = Byte.IsObject = String.IsObject = Int32.IsObject = Boolean.IsObject = Date.IsObject = Double.IsObject = false; 92 | 93 | Object.IsObject = true; 94 | 95 | // Conversion matrix 96 | // 97 | // SIDBFL 98 | // S100000 99 | // I110011 100 | // D101000 101 | // B100100 102 | // F100010 103 | // L100001 104 | // 105 | 106 | Int32.EnableConversionTo(Double); 107 | Int32.EnableConversionTo(Int64); 108 | 109 | DbNull.IsObject = false; 110 | 111 | Variant.IsInferable = DbNull.IsInferable = Nothing.IsInferable = false; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /ClrImporter.cs: -------------------------------------------------------------------------------- 1 | using FogCreek.Wasabi.AST; 2 | using Mono.Cecil; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | using CustomAttributeCollection = Mono.Collections.Generic.Collection; 10 | 11 | namespace FogCreek.Wasabi 12 | { 13 | /// 14 | /// Just enough to be able to declare return types! Very incomplete! 15 | /// 16 | public class ClrImporter 17 | { 18 | public static void LoadBuiltins(CProgram program) 19 | { 20 | ImportType(program, SearchAssembliesForType(program, "System.Object"), BuiltIns.Variant); 21 | ImportType(program, SearchAssembliesForType(program, "System.String"), BuiltIns.String); 22 | 23 | CClass vtype = program.FindClass("System.ValueType"); 24 | 25 | ImportType(program, SearchAssembliesForType(program, "System.Byte"), BuiltIns.Byte); 26 | BuiltIns.Byte.ForceSetBaseClass(vtype); 27 | ImportType(program, SearchAssembliesForType(program, "System.Int32"), BuiltIns.Int32); 28 | BuiltIns.Int32.ForceSetBaseClass(vtype); 29 | ImportType(program, SearchAssembliesForType(program, "System.Int64"), BuiltIns.Int64); 30 | BuiltIns.Int64.ForceSetBaseClass(vtype); 31 | ImportType(program, SearchAssembliesForType(program, "System.Char"), BuiltIns.Character); 32 | BuiltIns.Character.ForceSetBaseClass(vtype); 33 | ImportType(program, SearchAssembliesForType(program, "System.Boolean"), BuiltIns.Boolean); 34 | BuiltIns.Boolean.ForceSetBaseClass(vtype); 35 | ImportType(program, SearchAssembliesForType(program, "System.DateTime"), BuiltIns.Date); 36 | BuiltIns.Date.ForceSetBaseClass(vtype); 37 | ImportType(program, SearchAssembliesForType(program, "System.Double"), BuiltIns.Double); 38 | BuiltIns.Double.ForceSetBaseClass(vtype); 39 | 40 | BuiltIns.Variant.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(BuiltIns.Variant, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 41 | BuiltIns.Object.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(BuiltIns.Object, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 42 | BuiltIns.String.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(BuiltIns.String, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 43 | BuiltIns.Byte.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(BuiltIns.Byte, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 44 | BuiltIns.Int32.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(BuiltIns.Int32, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 45 | BuiltIns.Int64.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(BuiltIns.Int64, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 46 | BuiltIns.Character.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(BuiltIns.Character, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 47 | BuiltIns.Boolean.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(BuiltIns.Boolean, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 48 | BuiltIns.Date.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(BuiltIns.Date, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 49 | BuiltIns.Double.Attributes.Add(CToken.Identifer(null, "ExecuteAnywhere"), new CTypeRef(BuiltIns.Double, CToken.Identifer(null, "ExecuteAnywhereAttribute"))); 50 | } 51 | 52 | private static TypeDefinition SearchAssembliesForType(CProgram program, string name) 53 | { 54 | foreach (var asm in program.Assemblies) 55 | { 56 | var typed = asm.MainModule.Types.FirstOrDefault(td => td.FullName == name); 57 | if (typed != null) 58 | return typed; 59 | } 60 | 61 | return null; 62 | } 63 | 64 | private static bool IsClsCompliant(CustomAttributeCollection customAttributeCollection) 65 | { 66 | foreach (CustomAttribute attr in FindAttributes(customAttributeCollection, "System.CLSCompliantAttribute")) 67 | { 68 | if (attr.ConstructorArguments.Count > 0) 69 | return (bool)attr.ConstructorArguments[0].Value; 70 | } 71 | return true; 72 | } 73 | 74 | private static IEnumerable FindAttributes(CustomAttributeCollection attrs, string name) 75 | { 76 | if (attrs != null) 77 | foreach (CustomAttribute attr in attrs) 78 | { 79 | if (attr.Constructor.DeclaringType.FullName == name) 80 | yield return attr; 81 | } 82 | } 83 | 84 | private static void ImportType(CProgram program, TypeDefinition typed, CClass type) 85 | { 86 | if (type.CecilType != null) 87 | return; 88 | type.CecilType = typed; 89 | 90 | if (typed.GenericParameters.Count > 0 || !IsClsCompliant(typed.CustomAttributes)) 91 | return; 92 | 93 | 94 | if (typed.IsEnum) 95 | { 96 | type.IsObject = false; 97 | type.IsNumeric = true; 98 | } 99 | 100 | type.IsObject = !typed.IsValueType; 101 | 102 | type.SetSemanticallyComplete(); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /CompileException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FogCreek.Wasabi 4 | { 5 | [Serializable] 6 | public class CompileException : ApplicationException 7 | { 8 | internal readonly string filename; 9 | internal readonly string type; 10 | internal readonly int errno; 11 | internal readonly int line; 12 | internal readonly string source; 13 | 14 | private CompileException(string filename, string type, int errno, string message, int line, string source) 15 | : base(escape(message)) 16 | { 17 | this.filename = filename; 18 | this.type = type; 19 | this.errno = errno; 20 | this.line = line; 21 | this.source = escape(source); 22 | } 23 | 24 | internal static string escape(string str) 25 | { 26 | str = str.Replace("\n", @"\n"); 27 | str = str.Replace("\r", @"\r"); 28 | str = str.Replace("\t", @"\t"); 29 | return str; 30 | } 31 | 32 | internal static CompileException codegenFailed(string p) 33 | { 34 | return new CompileException("", "C", 1, p, 0, ""); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Compiler.cs: -------------------------------------------------------------------------------- 1 | using FogCreek.Wasabi.AST; 2 | 3 | namespace FogCreek.Wasabi 4 | { 5 | public enum CompilerPhase 6 | { 7 | Parsing, 8 | TypeChecking, 9 | XmlGenerating, 10 | CodeGenerating, 11 | } 12 | 13 | public class Compiler 14 | { 15 | public static Compiler Current { get; set; } 16 | 17 | public bool DefaultNamespaceSet { get; set; } 18 | public CToken DefaultNamespace { get; set; } 19 | 20 | 21 | public AST.NodeStateMode CurrentMode { get; set; } 22 | 23 | public CompilerPhase CurrentPhase { get; set; } 24 | 25 | public string OutputPath { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Example/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Example/Example.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C16DB98C-655F-493E-8751-9AC8A3ACC6F2} 8 | Exe 9 | Properties 10 | Example 11 | Example 12 | v4.5.1 13 | 512 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | False 38 | ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll 39 | 40 | 41 | ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Mdb.dll 42 | 43 | 44 | ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Pdb.dll 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | {19dfae1f-fb84-4771-b6d7-f4526875a6e1} 64 | WasabiRoslynGenerator 65 | True 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /Example/Program.cs: -------------------------------------------------------------------------------- 1 | using FogCreek.Wasabi; 2 | using FogCreek.Wasabi.AST; 3 | using FogCreek.Wasabi.CodeGenerators; 4 | using System; 5 | using System.IO; 6 | using System.Linq; 7 | 8 | namespace Example 9 | { 10 | class Program 11 | { 12 | /// A single optional arg tells the program where to cram its output 13 | static int Main() 14 | { 15 | CProgram.Global.Assemblies.Add(new Mono.Cecil.DefaultAssemblyResolver().Resolve(typeof(object).Assembly.FullName)); 16 | 17 | ClrImporter.LoadBuiltins(CProgram.Global); 18 | 19 | var compiler = Compiler.Current = new Compiler 20 | { 21 | DefaultNamespaceSet = true, 22 | DefaultNamespace = new CToken(null, TokenTypes.identifier, "Output"), 23 | OutputPath = "was_out" 24 | }; 25 | 26 | var rg = new RoslynGenerator(); 27 | IVisitor irg = rg; 28 | 29 | irg.VisitProgram(CProgram.Global); 30 | irg.VisitFile(FakeFile); 31 | 32 | rg.RootFile("root.cs"); 33 | return 0; 34 | } 35 | 36 | private const string FILE = "example.was"; 37 | 38 | public static CFile FakeFile 39 | { 40 | get 41 | { 42 | var file = new CFile(FILE, Path.Combine(Directory.GetCurrentDirectory(), FILE)); 43 | file.Statements.Add(MainClass); 44 | 45 | return file; 46 | } 47 | } 48 | 49 | public static CClass MainClass 50 | { 51 | get 52 | { 53 | var @class = new CClass(new CToken(FILE, TokenTypes.identifier, "Example"), "Example"); 54 | 55 | @class.SetClassMember("Main", new CMethod(MainFunc)); 56 | 57 | @class.SetSemanticallyComplete(); 58 | 59 | return @class; 60 | } 61 | } 62 | 63 | public static CFunction MainFunc 64 | { 65 | get 66 | { 67 | var func = new CFunction(new CToken(FILE, TokenTypes.identifier, "Main"), 68 | "Main", "Main", 69 | TokenTypes.visPrivate, 70 | CFunction.vbFunction, 71 | new CArgumentList(), 72 | BuiltIns.Int32.Type); 73 | func.IsStatic = true; 74 | 75 | AddBody(func.Statements); 76 | 77 | return func; 78 | } 79 | } 80 | 81 | public static void AddBody(CStatementBlock block) 82 | { 83 | block.Add(new CComment(new CToken(FILE, TokenTypes.comment, "' This is an example"), " This is an example")); 84 | 85 | block.Add(new CReturn(new CToken(FILE, TokenTypes.keyword, "Return")) 86 | { 87 | Expression = new CConstantExpression(new CToken(FILE, TokenTypes.number, "5")) 88 | }); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Example/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Example")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Example")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3195facb-bdab-410b-9889-4415439d627b")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ICodeGenVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using FogCreek.Wasabi.AST; 4 | 5 | namespace FogCreek.Wasabi 6 | { 7 | internal interface IInterceptor 8 | { 9 | void Option(COption option, CodeGenVisitor generator); 10 | void EnterFunction(CFunction function, CodeGenVisitor generator); 11 | void ExitFunction(CFunction function, CodeGenVisitor generator); 12 | } 13 | 14 | internal interface ICodeGenAcceptor : IVisitor 15 | { 16 | Object PreAcceptThen(CIf cif, Object state); 17 | void PreAcceptElse(CIf cif, Object state); 18 | void PreAcceptEndIf(CIf cif, Object state); 19 | void EnterFunction(CFunction function); 20 | void ExitFunction(CFunction function); 21 | } 22 | 23 | public interface ICodeGenVisitor : IVisitor 24 | { 25 | void InstrumentNode(CNode node, int num); 26 | void PreVisitFile(CFile file); 27 | 28 | IVisitor Acceptor { get; set; } 29 | 30 | void print(string s); 31 | void println(string s); 32 | void println(); 33 | } 34 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Fog Creek Software, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FogCreek.Wasabi 4 | { 5 | static class Program 6 | { 7 | public static void Main(string[] args) 8 | { 9 | Console.WriteLine("hello"); 10 | Console.ReadKey(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Wasabi Roslyn Generator")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Fog Creek Software")] 12 | [assembly: AssemblyProduct("FogCreek.Wasabi")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("924c31fc-4c89-41a1-ae8c-f4697d688ffa")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | [assembly: AssemblyVersion("1.0.0.0")] 33 | [assembly: AssemblyFileVersion("1.0.0.0")] 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wasabi RoslynGenerator 2 | 3 | This is the very back end of the Wasabi-to-C# compiler from Fog Creek Software. 4 | It converts a Wasabi abstract syntax tree (AST) into C# code. 5 | 6 | The CLR importer, lexer, parser, interpreter, type checker, language runtime, JavaScript generator, 7 | and other components of Wasabi are missing. 8 | 9 | It is intended to be used as an example for how to write a C# generator using Microsoft Roslyn. 10 | 11 | Build the solution in Visual Studio, then run `.\Example\bin\Debug\Example.exe` from the root of the repository. 12 | 13 | A very tiny program will be generated in `was_out`. 14 | -------------------------------------------------------------------------------- /RoslynExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System; 5 | 6 | namespace FogCreek.Wasabi.CodeGenerators 7 | { 8 | static class RoslynExtensions 9 | { 10 | public static TypeDeclarationSyntax WithBaseList(this TypeDeclarationSyntax node, BaseListSyntax list) 11 | { 12 | switch (node.Kind()) 13 | { 14 | case SyntaxKind.ClassDeclaration: 15 | return ((ClassDeclarationSyntax)node).WithBaseList(list); 16 | case SyntaxKind.InterfaceDeclaration: 17 | return ((InterfaceDeclarationSyntax)node).WithBaseList(list); 18 | case SyntaxKind.StructDeclaration: 19 | return ((StructDeclarationSyntax)node).WithBaseList(list); 20 | } 21 | throw new NotImplementedException("WithBaseList " + node.Kind().ToString()); 22 | } 23 | 24 | public static TypeDeclarationSyntax WithModifiers(this TypeDeclarationSyntax node, SyntaxTokenList modifiers) 25 | { 26 | switch (node.Kind()) 27 | { 28 | case SyntaxKind.ClassDeclaration: 29 | return ((ClassDeclarationSyntax)node).WithModifiers(modifiers); 30 | case SyntaxKind.InterfaceDeclaration: 31 | return ((InterfaceDeclarationSyntax)node).WithModifiers(modifiers); 32 | case SyntaxKind.StructDeclaration: 33 | return ((StructDeclarationSyntax)node).WithModifiers(modifiers); 34 | } 35 | throw new NotImplementedException("WithModifiers " + node.Kind().ToString()); 36 | } 37 | 38 | public static BaseMethodDeclarationSyntax WithModifiers(this BaseMethodDeclarationSyntax node, SyntaxTokenList modifiers) 39 | { 40 | switch (node.Kind()) 41 | { 42 | case SyntaxKind.OperatorDeclaration: 43 | case SyntaxKind.ConversionOperatorDeclaration: 44 | throw new NotImplementedException("Wasabi doesn't have operators"); 45 | case SyntaxKind.MethodDeclaration: 46 | return ((MethodDeclarationSyntax)node).WithModifiers(modifiers); 47 | case SyntaxKind.ConstructorDeclaration: 48 | return ((ConstructorDeclarationSyntax)node).WithModifiers(modifiers); 49 | case SyntaxKind.DestructorDeclaration: 50 | return ((DestructorDeclarationSyntax)node).WithModifiers(modifiers); 51 | } 52 | throw new NotImplementedException("WithModifiers " + node.Kind().ToString()); 53 | } 54 | 55 | public static BasePropertyDeclarationSyntax WithModifiers(this BasePropertyDeclarationSyntax node, SyntaxTokenList modifiers) 56 | { 57 | switch (node.Kind()) 58 | { 59 | case SyntaxKind.IndexerDeclaration: 60 | return ((IndexerDeclarationSyntax)node).WithModifiers(modifiers); 61 | case SyntaxKind.PropertyDeclaration: 62 | return (((PropertyDeclarationSyntax)node)).WithModifiers(modifiers); 63 | } 64 | throw new NotImplementedException("WithModifiers " + node.Kind().ToString()); 65 | } 66 | 67 | public static BasePropertyDeclarationSyntax WithExplicitInterfaceSpecifier(this BasePropertyDeclarationSyntax node, ExplicitInterfaceSpecifierSyntax syntax) 68 | { 69 | switch (node.Kind()) 70 | { 71 | case SyntaxKind.IndexerDeclaration: 72 | return ((IndexerDeclarationSyntax)node).WithExplicitInterfaceSpecifier(syntax); 73 | case SyntaxKind.PropertyDeclaration: 74 | return (((PropertyDeclarationSyntax)node)).WithExplicitInterfaceSpecifier(syntax); 75 | } 76 | throw new NotImplementedException("WithExplicitInterfaceSpecifier " + node.Kind().ToString()); 77 | } 78 | 79 | public static BasePropertyDeclarationSyntax WithAccessorList(this BasePropertyDeclarationSyntax node, AccessorListSyntax accessorList) 80 | { 81 | switch (node.Kind()) 82 | { 83 | case SyntaxKind.IndexerDeclaration: 84 | return ((IndexerDeclarationSyntax)node).WithAccessorList(accessorList); 85 | case SyntaxKind.PropertyDeclaration: 86 | return (((PropertyDeclarationSyntax)node)).WithAccessorList(accessorList); 87 | } 88 | throw new NotImplementedException(); 89 | } 90 | 91 | public static TypeDeclarationSyntax AddMember(this TypeDeclarationSyntax node, MemberDeclarationSyntax member) 92 | { 93 | return node.WithMembers(node.Members.Add(member)); 94 | } 95 | 96 | public static TypeDeclarationSyntax WithMembers(this TypeDeclarationSyntax node, SyntaxList members) 97 | { 98 | switch (node.Kind()) 99 | { 100 | case SyntaxKind.ClassDeclaration: 101 | return ((ClassDeclarationSyntax)node).WithMembers(members); 102 | case SyntaxKind.InterfaceDeclaration: 103 | return ((InterfaceDeclarationSyntax)node).WithMembers(members); 104 | case SyntaxKind.StructDeclaration: 105 | return ((StructDeclarationSyntax)node).WithMembers(members); 106 | } 107 | throw new NotImplementedException("WithMembers " + node.Kind().ToString()); 108 | } 109 | 110 | public static TypeDeclarationSyntax WithAttributeLists(this TypeDeclarationSyntax node, SyntaxList attributes) 111 | { 112 | switch (node.Kind()) 113 | { 114 | case SyntaxKind.ClassDeclaration: 115 | return ((ClassDeclarationSyntax)node).WithAttributeLists(attributes); 116 | case SyntaxKind.InterfaceDeclaration: 117 | return ((InterfaceDeclarationSyntax)node).WithAttributeLists(attributes); 118 | case SyntaxKind.StructDeclaration: 119 | return ((StructDeclarationSyntax)node).WithAttributeLists(attributes); 120 | } 121 | 122 | throw new NotImplementedException("WithAttributeLists " + node.Kind().ToString()); 123 | } 124 | 125 | public static BaseMethodDeclarationSyntax WithAttributeLists(this BaseMethodDeclarationSyntax node, SyntaxList attributes) 126 | { 127 | switch (node.Kind()) 128 | { 129 | case SyntaxKind.OperatorDeclaration: 130 | case SyntaxKind.ConversionOperatorDeclaration: 131 | throw new NotImplementedException("Wasabi doesn't have operators"); 132 | case SyntaxKind.MethodDeclaration: 133 | return ((MethodDeclarationSyntax)node).WithAttributeLists(attributes); 134 | case SyntaxKind.ConstructorDeclaration: 135 | return ((ConstructorDeclarationSyntax)node).WithAttributeLists(attributes); 136 | case SyntaxKind.DestructorDeclaration: 137 | return ((DestructorDeclarationSyntax)node).WithAttributeLists(attributes); 138 | } 139 | 140 | throw new NotImplementedException("WithAttributeLists " + node.Kind().ToString()); 141 | } 142 | 143 | public static BaseMethodDeclarationSyntax WithParameterList(this BaseMethodDeclarationSyntax method, ParameterListSyntax pls) 144 | { 145 | switch (method.Kind()) 146 | { 147 | case SyntaxKind.OperatorDeclaration: 148 | case SyntaxKind.ConversionOperatorDeclaration: 149 | throw new NotImplementedException("Wasabi doesn't have operators"); 150 | case SyntaxKind.MethodDeclaration: 151 | return ((MethodDeclarationSyntax)method).WithParameterList(pls); 152 | case SyntaxKind.ConstructorDeclaration: 153 | return ((ConstructorDeclarationSyntax)method).WithParameterList(pls); 154 | case SyntaxKind.DestructorDeclaration: 155 | return ((DestructorDeclarationSyntax)method).WithParameterList(pls); 156 | } 157 | 158 | throw new NotImplementedException("WithParameterList " + method.Kind().ToString()); 159 | } 160 | 161 | public static BaseMethodDeclarationSyntax WithReturnType(this BaseMethodDeclarationSyntax method, TypeSyntax type) 162 | { 163 | switch (method.Kind()) 164 | { 165 | case SyntaxKind.OperatorDeclaration: 166 | case SyntaxKind.ConversionOperatorDeclaration: 167 | throw new NotImplementedException("Wasabi doesn't have operators"); 168 | case SyntaxKind.MethodDeclaration: 169 | return ((MethodDeclarationSyntax)method).WithReturnType(type); 170 | case SyntaxKind.ConstructorDeclaration: 171 | throw new InvalidOperationException("Constructors don't have return type"); 172 | case SyntaxKind.DestructorDeclaration: 173 | throw new InvalidOperationException("Destructors don't have return type"); 174 | } 175 | 176 | throw new NotImplementedException("WithReturnType " + method.Kind().ToString()); 177 | } 178 | 179 | 180 | public static BaseMethodDeclarationSyntax WithBody(this BaseMethodDeclarationSyntax method, BlockSyntax body) 181 | { 182 | switch (method.Kind()) 183 | { 184 | case SyntaxKind.OperatorDeclaration: 185 | case SyntaxKind.ConversionOperatorDeclaration: 186 | throw new NotImplementedException("Wasabi doesn't have operators"); 187 | case SyntaxKind.MethodDeclaration: 188 | return ((MethodDeclarationSyntax)method).WithBody(body); 189 | case SyntaxKind.ConstructorDeclaration: 190 | return ((ConstructorDeclarationSyntax)method).WithBody(body); 191 | case SyntaxKind.DestructorDeclaration: 192 | return ((DestructorDeclarationSyntax)method).WithBody(body); 193 | } 194 | 195 | throw new NotImplementedException("WithBody " + method.Kind().ToString()); 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /WasabiRoslynGenerator.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WasabiRoslynGenerator", "WasabiRoslynGenerator.csproj", "{19DFAE1F-FB84-4771-B6D7-F4526875A6E1}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example.csproj", "{C16DB98C-655F-493E-8751-9AC8A3ACC6F2}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {19DFAE1F-FB84-4771-B6D7-F4526875A6E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {19DFAE1F-FB84-4771-B6D7-F4526875A6E1}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {19DFAE1F-FB84-4771-B6D7-F4526875A6E1}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {19DFAE1F-FB84-4771-B6D7-F4526875A6E1}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {C16DB98C-655F-493E-8751-9AC8A3ACC6F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {C16DB98C-655F-493E-8751-9AC8A3ACC6F2}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {C16DB98C-655F-493E-8751-9AC8A3ACC6F2}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {C16DB98C-655F-493E-8751-9AC8A3ACC6F2}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /was_out/.gitignore: -------------------------------------------------------------------------------- 1 | *.cs 2 | --------------------------------------------------------------------------------