// AST.fu - Fusion abstract syntax tree
//
// Copyright (C) 2011-2026 Piotr Fusik
//
// This file is part of Fusion Transpiler,
// see https://github.com/fusionlanguage/fut
//
// Fusion Transpiler is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Fusion Transpiler is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Fusion Transpiler. If not, see http://www.gnu.org/licenses/
public enum FuVisibility
{
Private,
Internal,
Protected,
Public,
NumericElementType,
FinalValueType
}
public enum FuCallType
{
Static,
Normal,
Abstract,
Virtual,
Override,
Sealed
}
public enum FuPriority
{
Statement,
Argument,
Assign,
Select,
SelectCond,
CondOr,
CondAnd,
Or,
Xor,
And,
Equality,
Rel,
Shift,
Add,
Mul,
Primary
}
public enum FuId
{
None,
VoidType,
NullType,
BasePtr,
TypeParam0,
TypeParam0NotFinal,
TypeParam0Predicate,
TypeParam1,
SByteRange,
ByteRange,
ShortRange,
UShortRange,
IntType,
NIntType,
LongType,
FloatType,
DoubleType,
FloatIntType,
FloatingType,
NumericType,
BoolType,
StringClass,
StringPtrType,
StringStorageType,
MainArgsType,
ArrayPtrClass,
ArrayStorageClass,
ExceptionClass,
ListClass,
QueueClass,
StackClass,
PriorityQueueClass,
HashSetClass,
SortedSetClass,
DictionaryClass,
SortedDictionaryClass,
OrderedDictionaryClass,
TextWriterClass,
StringWriterClass,
RegexOptionsEnum,
RegexClass,
MatchClass,
JsonElementClass,
LockClass,
StringLength,
ArrayLength,
ConsoleError,
ConsoleOut,
Main,
ClassToString,
MatchStart,
MatchEnd,
MatchLength,
MatchValue,
MathNaN,
MathNegativeInfinity,
MathPositiveInfinity,
EnumFromInt,
EnumHasFlag,
EnumToInt,
IntTryParse,
NIntTryParse,
LongTryParse,
FloatTryParse,
DoubleTryParse,
StringContains,
StringEndsWith,
StringIndexOf,
StringLastIndexOf,
StringReplace,
StringStartsWith,
StringSubstring,
StringToLower,
StringToUpper,
ArrayBinarySearchAll,
ArrayBinarySearchPart,
ArrayContains,
ArrayCopyTo,
ArrayFillAll,
ArrayFillPart,
ArraySortAll,
ArraySortPart,
ListAdd,
ListAddRange,
ListAll,
ListAny,
ListClear,
ListContains,
ListCopyTo,
ListCount,
ListIndexOf,
ListInsert,
ListLast,
ListRemoveAt,
ListRemoveRange,
ListSortAll,
ListSortPart,
QueueClear,
QueueCount,
QueueDequeue,
QueueEnqueue,
QueuePeek,
StackClear,
StackCount,
StackPeek,
StackPush,
StackPop,
PriorityQueueClear,
PriorityQueueCount,
PriorityQueueDequeue,
PriorityQueueEnqueue,
PriorityQueuePeek,
HashSetAdd,
HashSetClear,
HashSetContains,
HashSetCount,
HashSetRemove,
SortedSetAdd,
SortedSetClear,
SortedSetContains,
SortedSetCount,
SortedSetRemove,
DictionaryAdd,
DictionaryClear,
DictionaryContainsKey,
DictionaryCount,
DictionaryRemove,
SortedDictionaryClear,
SortedDictionaryContainsKey,
SortedDictionaryCount,
SortedDictionaryRemove,
OrderedDictionaryClear,
OrderedDictionaryContainsKey,
OrderedDictionaryCount,
OrderedDictionaryRemove,
TextWriterFlush,
TextWriterWrite,
TextWriterWriteChar,
TextWriterWriteCodePoint,
TextWriterWriteLine,
ConsoleReadLine,
ConsoleWrite,
ConsoleWriteLine,
StringWriterClear,
StringWriterToString,
BitConverterInt32BitsToSingle,
BitConverterInt64BitsToDouble,
BitConverterSingleToInt32Bits,
BitConverterDoubleToInt64Bits,
ConvertToBase64String,
UTF8GetByteCount,
UTF8GetBytes,
UTF8GetString,
EnvironmentGetEnvironmentVariable,
DateTimeOffsetUtcNowToUnixTimeMilliseconds,
RegexCompile,
RegexEscape,
RegexIsMatchStr,
RegexIsMatchRegex,
MatchFindStr,
MatchFindRegex,
MatchGetCapture,
JsonElementParse,
JsonElementIsObject,
JsonElementIsArray,
JsonElementIsString,
JsonElementIsNumber,
JsonElementIsBoolean,
JsonElementIsNull,
JsonElementGetObject,
JsonElementGetArray,
JsonElementGetString,
JsonElementGetDouble,
JsonElementGetBoolean,
MathMethod,
MathAbs,
MathCeiling,
MathClamp,
MathFusedMultiplyAdd,
MathIsFinite,
MathIsInfinity,
MathIsNaN,
MathLog2,
MathMax,
MathMin,
MathRound,
MathSqrt,
MathTruncate
}
public abstract class FuDocInline
{
}
public class FuDocText : FuDocInline
{
internal string() Text;
}
public class FuDocCode : FuDocInline
{
internal string() Text;
}
public class FuDocLine : FuDocInline
{
}
public abstract class FuDocBlock
{
}
public class FuDocPara : FuDocBlock
{
internal List<FuDocInline#>() Children;
}
public class FuDocList : FuDocBlock
{
internal List<FuDocPara()>() Items;
}
public class FuCodeDoc
{
internal FuDocPara() Summary;
internal List<FuDocBlock#>() Details;
}
public abstract class FuVisitor
{
protected void VisitOptionalStatement!(FuStatement? statement)
{
if (statement != null)
statement.AcceptStatement(this);
}
internal abstract void VisitConst!(FuConst statement);
internal abstract void VisitExpr!(FuExpr statement);
internal abstract void VisitBlock!(FuBlock statement);
internal abstract void VisitAssert!(FuAssert statement);
internal abstract void VisitBreak!(FuBreak statement);
internal abstract void VisitContinue!(FuContinue statement);
internal abstract void VisitDoWhile!(FuDoWhile statement);
internal abstract void VisitFor!(FuFor statement);
internal abstract void VisitForeach!(FuForeach statement);
internal abstract void VisitIf!(FuIf statement);
internal abstract void VisitLock!(FuLock statement);
internal abstract void VisitNative!(FuNative statement);
internal abstract void VisitReturn!(FuReturn statement);
internal abstract void VisitSwitch!(FuSwitch statement);
internal abstract void VisitThrow!(FuThrow statement);
internal abstract void VisitWhile!(FuWhile statement);
internal abstract void VisitEnumValue!(FuConst konst, FuConst? previous);
internal abstract void VisitLiteralNull!();
internal abstract void VisitLiteralFalse!();
internal abstract void VisitLiteralTrue!();
internal abstract void VisitLiteralLong!(long value, FuPriority parent);
internal abstract void VisitLiteralChar!(int value);
internal abstract void VisitLiteralDouble!(double value);
internal abstract void VisitLiteralString!(string value);
internal abstract void VisitAggregateInitializer!(FuAggregateInitializer expr);
internal abstract void VisitInterpolatedString!(FuInterpolatedString expr, FuPriority parent);
internal abstract void VisitSymbolReference!(FuSymbolReference expr, FuPriority parent);
internal abstract void VisitPrefixExpr!(FuPrefixExpr expr, FuPriority parent);
internal abstract void VisitPostfixExpr!(FuPostfixExpr expr, FuPriority parent);
internal abstract void VisitBinaryExpr!(FuBinaryExpr expr, FuPriority parent);
internal abstract void VisitSelectExpr!(FuSelectExpr expr, FuPriority parent);
internal abstract void VisitCallExpr!(FuCallExpr expr, FuPriority parent);
internal abstract void VisitLambdaExpr!(FuLambdaExpr expr);
internal abstract void VisitVar!(FuVar expr);
}
public abstract class FuStatement
{
internal int Loc = 0;
public virtual int GetLocLength() => 0;
public abstract bool CompletesNormally();
public abstract void AcceptStatement(FuVisitor! visitor);
}
public abstract class FuExpr : FuStatement
{
internal FuType#? Type;
public override bool CompletesNormally() => true;
public virtual string() ToString() { assert false; }
public virtual bool HasSideEffect() => false;
public virtual bool IsIndexing() => false;
public virtual bool IsLiteralZero() => false;
public virtual int IntValue() { assert false; }
public virtual bool IsConst(bool varIsConst) => false;
public virtual void Accept(FuVisitor! visitor, FuPriority parent) { assert false; }
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitExpr(this); }
public virtual bool IsReferenceTo(FuSymbol symbol) => false;
public virtual bool IsNewString(bool substringOffset) => false;
public virtual bool IsUnique() => false;
public virtual void SetShared() { }
}
public abstract class FuName : FuExpr
{
internal string() Name = "";
public override int GetLocLength() => this.Name.Length;
public abstract FuSymbol? GetSymbol();
}
public abstract class FuSymbol : FuName
{
internal FuId Id = FuId.None;
internal FuSymbol!? Next;
internal FuScope!? Parent;
internal FuCodeDoc#? Documentation = null;
public override FuSymbol? GetSymbol() => this;
public override string() ToString() => this.Name;
}
public abstract class FuScope : FuSymbol
{
protected Dictionary<string, FuSymbol#>() Dict;
internal FuSymbol!? First = null;
internal FuSymbol!? Last = null;
public int Count() => this.Dict.Count;
public bool Contains(FuSymbol symbol) => this.Dict.ContainsKey(symbol.Name);
public FuSymbol#? TryLookup(string name, bool global)
{
for (FuScope? scope = this; scope != null && (global || !(scope is FuProgram || scope is FuSystem)); scope = scope.Parent) {
if (scope.Dict.ContainsKey(name))
return scope.Dict[name];
}
return null;
}
protected void AddToList!(FuSymbol# symbol)
{
symbol.Next = null;
symbol.Parent = this;
if (this.First == null)
this.First = symbol;
else
this.Last.Next = symbol;
this.Last = symbol;
}
public void Add!(FuSymbol# symbol)
{
this.Dict[symbol.Name] = symbol;
AddToList(symbol);
}
public bool Encloses(FuSymbol symbol)
{
for (FuScope? scope = symbol.Parent; scope != null; scope = scope.Parent) {
if (scope == this)
return true;
}
return false;
}
}
public class FuAggregateInitializer : FuExpr
{
internal List<FuExpr#>() Items;
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitAggregateInitializer(this); }
}
public abstract class FuLiteral : FuExpr
{
public override bool IsConst(bool varIsConst) => true;
public abstract bool IsDefaultValue();
public virtual string() GetLiteralString() { assert false; }
}
class FuLiteralNull : FuLiteral
{
public override int GetLocLength() => 4;
public override bool IsDefaultValue() => true;
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitLiteralNull(); }
public override bool IsUnique() => true;
public override string() ToString() => "null";
}
class FuLiteralFalse : FuLiteral
{
public override int GetLocLength() => 5;
public override bool IsDefaultValue() => true;
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitLiteralFalse(); }
public override string() ToString() => "false";
}
class FuLiteralTrue : FuLiteral
{
public override int GetLocLength() => 4;
public override bool IsDefaultValue() => false;
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitLiteralTrue(); }
public override string() ToString() => "true";
}
class FuLiteralLong : FuLiteral
{
internal long Value;
public override bool IsLiteralZero() => this.Value == 0;
public override int IntValue() => this.Value;
public override bool IsDefaultValue() => this.Value == 0;
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitLiteralLong(this.Value, parent); }
public override string() GetLiteralString() => $"{this.Value}";
public override string() ToString() => $"{this.Value}";
}
class FuLiteralChar : FuLiteralLong
{
public static FuLiteralChar# New(int value, int loc) => new FuLiteralChar { Loc = loc, Type = FuRangeType.New(value, value), Value = value };
public override int GetLocLength() => this.Value >= 0x10000 || this.Value == '\n' || this.Value == '\r' || this.Value == '\t' || this.Value == '\\' || this.Value == '\'' ? 4 : 3;
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitLiteralChar(this.Value); }
// public override string() ToString()
// {
// switch (this.Value) {
// case '\n': return "'\\n'";
// case '\r': return "'\\r'";
// case '\t': return "'\\t'";
// case '\\': return "'\\\\'";
// case '\'': return "'\\''";
// default: return $"'{(char) this.Value}'";
// }
// }
}
class FuLiteralDouble : FuLiteral
{
internal double Value;
public override bool IsDefaultValue() => this.Value == 0 && 1.0 / this.Value > 0; // rule out -0.0
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitLiteralDouble(this.Value); }
public override string() GetLiteralString() => $"{this.Value}";
public override string() ToString() => $"{this.Value}";
}
class FuLiteralString : FuLiteral
{
internal string() Value;
public override bool IsDefaultValue() => false;
public override int GetLocLength() => this.Value.Length + 2;
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitLiteralString(this.Value); }
public override string() GetLiteralString() => this.Value;
public override string() ToString() => $"\"{this.Value}\"";
public int GetAsciiLength()
{
int length = 0;
bool escaped = false;
foreach (int c in this.Value) {
if (c < 0 || c > 127)
return -1;
if (!escaped && c == '\\')
escaped = true;
else {
length++;
escaped = false;
}
}
return length;
}
public int GetAsciiAt(int i)
{
bool escaped = false;
foreach (int c in this.Value) {
if (c < 0 || c > 127)
return -1;
if (!escaped && c == '\\')
escaped = true;
else if (i == 0)
return escaped ? FuLexer.GetEscapedChar(c) : c;
else {
i--;
escaped = false;
}
}
return -1;
}
public int GetOneAscii()
{
switch (this.Value.Length) {
case 1:
int c = this.Value[0];
return c >= 0 && c <= 127 ? c : -1;
case 2:
return this.Value[0] == '\\' ? FuLexer.GetEscapedChar(this.Value[1]) : -1;
default:
return -1;
}
}
}
public class FuInterpolatedPart
{
internal string() Prefix;
internal FuExpr# Argument;
internal FuExpr#? WidthExpr;
internal int Width;
internal int Format;
internal int Precision;
}
public class FuInterpolatedString : FuExpr
{
internal List<FuInterpolatedPart()>() Parts;
internal string() Suffix;
public void AddPart!(string prefix, FuExpr# arg, FuExpr#? widthExpr = null, int format = ' ', int precision = -1)
{
this.Parts.Add();
FuInterpolatedPart! part = this.Parts.Last();
part.Prefix = prefix;
part.Argument = arg;
part.WidthExpr = widthExpr;
part.Format = format;
part.Precision = precision;
}
public override int GetLocLength() => 2; // FIXME
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitInterpolatedString(this, parent); }
// public override bool IsConst(bool varIsConst) => this.Parts.All(part => part.Argument.IsConst(varIsConst));
public override bool IsNewString(bool substringOffset) => true;
public bool IsToString(int format)
{
return this.Suffix.Length == 0
&& this.Parts.Count == 1
&& this.Parts[0].Prefix.Length == 0
&& this.Parts[0].WidthExpr == null
&& (this.Parts[0].Format | 0x20) == format;
}
// public override string() ToString()
// {
// StringBuilder sb = new StringBuilder();
// sb.Append("$\"");
// foreach (FuInterpolatedPart part in this.Parts) {
// sb.Append(part.Prefix.Replace("{", "{{"));
// sb.Append('{');
// sb.Append(part.Argument);
// if (part.WidthExpr != null) {
// sb.Append(',');
// sb.Append(part.WidthExpr);
// }
// if (part.Format != ' ') {
// sb.Append(':');
// sb.Append((char) part.Format);
// if (part.Precision >= 0)
// sb.Append(part.Precision);
// }
// sb.Append('}');
// }
// sb.Append(this.Suffix.Replace("{", "{{"));
// sb.Append('"');
// return sb.ToString();
// }
}
class FuImplicitEnumValue : FuExpr
{
internal int Value;
public override int IntValue() => this.Value;
}
public class FuSymbolReference : FuName
{
internal FuExpr#? Left = null;
internal FuSymbol!? Symbol;
public override int IntValue()
{
assert this.Symbol is FuConst konst;
return konst.Value.IntValue();
}
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitSymbolReference(this, parent); }
public override bool IsReferenceTo(FuSymbol symbol) => this.Symbol == symbol;
public override bool IsConst(bool varIsConst) => this.Symbol.IsConst(varIsConst) && (this.Left == null || this.Left.IsConst(varIsConst));
public override bool IsNewString(bool substringOffset) => this.Symbol.Id == FuId.MatchValue;
public override void SetShared()
{
if (this.Symbol is FuNamedValue varOrField && varOrField.Type is FuDynamicPtrType! dynamic)
dynamic.Unique = false;
}
public override FuSymbol? GetSymbol() => this.Symbol;
public override string() ToString() => this.Left != null ? $"{this.Left}.{this.Name}" : this.Name;
}
public abstract class FuUnaryExpr : FuExpr
{
internal FuToken Op;
internal FuExpr#? Inner;
public override int GetLocLength()
{
switch (this.Op) {
case FuToken.Increment:
case FuToken.Decrement:
return 2;
case FuToken.Minus:
case FuToken.Tilde:
case FuToken.ExclamationMark:
case FuToken.Hash:
case FuToken.QuestionMark:
return 1;
case FuToken.New:
return 3;
case FuToken.Resource:
return 8;
default:
assert false;
}
}
}
public class FuPrefixExpr : FuUnaryExpr
{
public override int IntValue()
{
assert this.Op == FuToken.Tilde;
return ~this.Inner.IntValue();
}
public override bool HasSideEffect() => this.Op == FuToken.Increment || this.Op == FuToken.Decrement;
public override bool IsConst(bool varIsConst) => (this.Op == FuToken.Minus || this.Op == FuToken.Tilde || this.Op == FuToken.ExclamationMark || this.Op == FuToken.Resource) && this.Inner.IsConst(varIsConst);
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitPrefixExpr(this, parent); }
public override bool IsUnique() => this.Op == FuToken.New && !(this.Inner is FuAggregateInitializer);
}
public class FuPostfixExpr : FuUnaryExpr
{
public override bool HasSideEffect() => true;
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitPostfixExpr(this, parent); }
}
public class FuBinaryExpr : FuExpr
{
internal FuExpr# Left;
internal FuToken Op;
internal FuExpr#? Right;
public override int GetLocLength()
{
switch (this.Op) {
case FuToken.LeftBracket:
case FuToken.LeftBrace:
case FuToken.Plus:
case FuToken.Minus:
case FuToken.Asterisk:
case FuToken.Slash:
case FuToken.Mod:
case FuToken.And:
case FuToken.Or:
case FuToken.Xor:
case FuToken.Less:
case FuToken.Greater:
case FuToken.Assign:
return 1;
case FuToken.ShiftLeft:
case FuToken.ShiftRight:
case FuToken.Equal:
case FuToken.NotEqual:
case FuToken.LessOrEqual:
case FuToken.GreaterOrEqual:
case FuToken.CondAnd:
case FuToken.CondOr:
case FuToken.AddAssign:
case FuToken.SubAssign:
case FuToken.MulAssign:
case FuToken.DivAssign:
case FuToken.ModAssign:
case FuToken.AndAssign:
case FuToken.OrAssign:
case FuToken.XorAssign:
case FuToken.Is:
return 2;
case FuToken.ShiftLeftAssign:
case FuToken.ShiftRightAssign:
return 3;
case FuToken.When:
return 0;
default:
assert false;
}
}
public override bool IsIndexing() => this.Op == FuToken.LeftBracket;
public override int IntValue()
{
switch (this.Op) {
case FuToken.And:
return this.Left.IntValue() & this.Right.IntValue();
case FuToken.Or:
return this.Left.IntValue() | this.Right.IntValue();
case FuToken.Xor:
return this.Left.IntValue() ^ this.Right.IntValue();
default:
assert false;
}
}
public override bool IsConst(bool varIsConst) => this.Left.IsConst(varIsConst) && this.Right.IsConst(varIsConst);
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitBinaryExpr(this, parent); }
public override bool IsNewString(bool substringOffset) => this.Op == FuToken.Plus && this.Type.Id == FuId.StringStorageType;
public bool IsRel()
{
switch (this.Op) {
case FuToken.Equal:
case FuToken.NotEqual:
case FuToken.Less:
case FuToken.LessOrEqual:
case FuToken.Greater:
case FuToken.GreaterOrEqual:
return true;
default:
return false;
}
}
public override bool HasSideEffect()
{
switch (this.Op) {
case FuToken.Assign:
case FuToken.AddAssign:
case FuToken.SubAssign:
case FuToken.MulAssign:
case FuToken.DivAssign:
case FuToken.ModAssign:
case FuToken.AndAssign:
case FuToken.OrAssign:
case FuToken.XorAssign:
case FuToken.ShiftLeftAssign:
case FuToken.ShiftRightAssign:
return true;
default:
return false;
}
}
public string GetOpString()
{
switch (this.Op) {
case FuToken.Plus:
return "+";
case FuToken.Minus:
return "-";
case FuToken.Asterisk:
return "*";
case FuToken.Slash:
return "/";
case FuToken.Mod:
return "%";
case FuToken.ShiftLeft:
return "<<";
case FuToken.ShiftRight:
return ">>";
case FuToken.Less:
return "<";
case FuToken.LessOrEqual:
return "<=";
case FuToken.Greater:
return ">";
case FuToken.GreaterOrEqual:
return ">=";
case FuToken.Equal:
return "==";
case FuToken.NotEqual:
return "!=";
case FuToken.And:
return "&";
case FuToken.Or:
return "|";
case FuToken.Xor:
return "^";
case FuToken.CondAnd:
return "&&";
case FuToken.CondOr:
return "||";
case FuToken.Assign:
return "=";
case FuToken.AddAssign:
return "+=";
case FuToken.SubAssign:
return "-=";
case FuToken.MulAssign:
return "*=";
case FuToken.DivAssign:
return "/=";
case FuToken.ModAssign:
return "%=";
case FuToken.ShiftLeftAssign:
return "<<=";
case FuToken.ShiftRightAssign:
return ">>=";
case FuToken.AndAssign:
return "&=";
case FuToken.OrAssign:
return "|=";
case FuToken.XorAssign:
return "^=";
default:
assert false;
}
}
public override string() ToString() => this.Op == FuToken.LeftBracket ? $"{this.Left}[{this.Right}]" : $"({this.Left} {GetOpString()} {this.Right})";
}
public class FuSelectExpr : FuExpr
{
internal FuExpr# Cond;
internal FuExpr# OnTrue;
internal FuExpr# OnFalse;
public override int GetLocLength() => 1;
public override bool IsConst(bool varIsConst) => this.Cond.IsConst(varIsConst) && this.OnTrue.IsConst(varIsConst) && this.OnFalse.IsConst(varIsConst);
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitSelectExpr(this, parent); }
public override bool IsUnique() => this.OnTrue.IsUnique() && this.OnFalse.IsUnique();
public override void SetShared()
{
this.OnTrue.SetShared();
this.OnFalse.SetShared();
}
public override string() ToString() => $"({this.Cond} ? {this.OnTrue} : {this.OnFalse})";
}
public class FuCallExpr : FuExpr
{
internal FuSymbolReference# Method;
internal List<FuExpr#>() Arguments;
public override bool HasSideEffect() => true;
public override bool IsConst(bool varIsConst)
{
assert this.Method.Symbol is FuMethod method;
return method.IsPure() && this.Arguments.All(arg => arg.IsConst(varIsConst));
}
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitCallExpr(this, parent); }
public override bool IsNewString(bool substringOffset)
=> this.Type.Id == FuId.StringStorageType
&& this.Method.Symbol.Id != FuId.ListLast && this.Method.Symbol.Id != FuId.QueuePeek && this.Method.Symbol.Id != FuId.StackPeek
&& (substringOffset || this.Method.Symbol.Id != FuId.StringSubstring || this.Arguments.Count != 1);
public override string() ToString() => this.Method.Name;
}
class FuLambdaExpr : FuScope
{
internal FuExpr# Body;
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitLambdaExpr(this); }
}
public abstract class FuCondCompletionStatement : FuScope
{
bool CompletesNormallyValue;
public override bool CompletesNormally() => this.CompletesNormallyValue;
public void SetCompletesNormally!(bool value) { this.CompletesNormallyValue = value; }
}
public class FuBlock : FuCondCompletionStatement
{
internal List<FuStatement#>() Statements;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitBlock(this); }
}
public class FuAssert : FuStatement
{
internal FuExpr# Cond;
internal FuExpr#? Message = null;
public override int GetLocLength() => 6;
public override bool CompletesNormally() => !(this.Cond is FuLiteralFalse);
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitAssert(this); }
}
public abstract class FuLoop : FuCondCompletionStatement
{
internal FuExpr#? Cond;
internal FuStatement# Body;
internal bool HasBreak = false;
}
class FuBreak : FuStatement
{
internal FuCondCompletionStatement! LoopOrSwitch;
public override int GetLocLength() => 5;
public override bool CompletesNormally() => false;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitBreak(this); }
}
class FuContinue : FuStatement
{
internal FuLoop Loop;
public override int GetLocLength() => 8;
public override bool CompletesNormally() => false;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitContinue(this); }
}
class FuDoWhile : FuLoop
{
public override int GetLocLength() => 2;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitDoWhile(this); }
}
class FuFor : FuLoop
{
internal FuExpr#? Init;
internal FuExpr#? Advance;
internal bool IsRange = false;
internal bool IsIndVarUsed;
internal long RangeStep;
public override int GetLocLength() => 3;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitFor(this); }
}
class FuForeach : FuLoop
{
internal FuExpr# Collection;
public override int GetLocLength() => 7;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitForeach(this); }
public FuVar! GetVar()
{
assert this.First is FuVar! result;
return result;
}
public FuVar! GetValueVar() => this.GetVar().NextVar();
}
class FuIf : FuCondCompletionStatement
{
internal FuExpr# Cond;
internal FuStatement# OnTrue;
internal FuStatement#? OnFalse;
public override int GetLocLength() => 2;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitIf(this); }
}
class FuLock : FuStatement
{
internal FuExpr# Lock;
internal FuStatement# Body;
public override int GetLocLength() => 4;
public override bool CompletesNormally() => this.Body.CompletesNormally();
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitLock(this); }
}
public class FuNative : FuSymbol
{
internal string() Content;
public override int GetLocLength() => 6;
public override bool CompletesNormally() => true;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitNative(this); }
public FuMember? GetFollowingMember()
{
for (FuSymbol? symbol = this.Next; symbol != null; symbol = symbol.Next) {
if (symbol is FuMember member)
return member;
}
return null;
}
}
class FuReturn : FuScope
{
internal FuExpr#? Value;
public override int GetLocLength() => 6;
public override bool CompletesNormally() => false;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitReturn(this); }
}
public class FuCase
{
internal List<FuExpr#>() Values;
internal List<FuStatement#>() Body;
}
public class FuSwitch : FuCondCompletionStatement
{
internal FuExpr# Value;
internal List<FuCase()>() Cases;
internal List<FuStatement#>() DefaultBody;
public override int GetLocLength() => 6;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitSwitch(this); }
public bool IsTypeMatching() => this.Value.Type is FuClassType klass && klass.Class.Id != FuId.StringClass;
public bool HasWhen() => this.Cases.Any(kase => kase.Values.Any(value => value is FuBinaryExpr when1 && when1.Op == FuToken.When));
public static int LengthWithoutTrailingBreak(List<FuStatement#> body)
{
int length = body.Count;
if (length > 0 && body[length - 1] is FuBreak)
length--;
return length;
}
public bool HasDefault() => LengthWithoutTrailingBreak(this.DefaultBody) > 0;
static bool HasBreak(FuStatement statement)
{
switch (statement) {
case FuBreak:
return true;
case FuIf ifStatement:
return HasBreak(ifStatement.OnTrue) || (ifStatement.OnFalse != null && HasBreak(ifStatement.OnFalse));
case FuBlock block:
return block.Statements.Any(child => HasBreak(child));
default:
return false;
}
}
public static bool HasEarlyBreak(List<FuStatement#> body)
{
int length = LengthWithoutTrailingBreak(body);
for (int i = 0; i < length; i++) {
if (HasBreak(body[i]))
return true;
}
return false;
}
static bool ListHasContinue(List<FuStatement#> statements) => statements.Any(statement => HasContinue(statement));
static bool HasContinue(FuStatement statement)
{
switch (statement) {
case FuContinue:
return true;
case FuIf ifStatement:
return HasContinue(ifStatement.OnTrue) || (ifStatement.OnFalse != null && HasContinue(ifStatement.OnFalse));
case FuSwitch switchStatement:
return switchStatement.Cases.Any(kase => ListHasContinue(kase.Body)) || ListHasContinue(switchStatement.DefaultBody);
case FuBlock block:
return ListHasContinue(block.Statements);
default:
return false;
}
}
public static bool HasEarlyBreakAndContinue(List<FuStatement#> body) => HasEarlyBreak(body) && ListHasContinue(body);
}
public class FuThrow : FuStatement
{
internal FuSymbolReference# Class;
internal FuExpr#? Message;
public override int GetLocLength() => 5;
public override bool CompletesNormally() => false;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitThrow(this); }
}
class FuWhile : FuLoop
{
public override int GetLocLength() => 5;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitWhile(this); }
}
public class FuParameters : FuScope
{
}
public class FuType : FuScope
{
internal bool Nullable = false;
public virtual string() GetArraySuffix() => "";
public virtual bool IsAssignableFrom(FuType right) => this == right;
public virtual bool EqualsType(FuType right) => this == right;
public virtual bool IsArray() => false;
public virtual bool IsFinal() => false;
public virtual FuType GetBaseType() => this;
public virtual FuType GetStorageType() => this;
public FuClassType AsClassType()
{
assert this is FuClassType klass;
return klass;
}
}
class FuNumericType : FuType
{
}
class FuIntegerType : FuNumericType
{
public override bool IsAssignableFrom(FuType right) => right is FuIntegerType || right.Id == FuId.FloatIntType;
}
class FuRangeType : FuIntegerType
{
internal int Min;
internal int Max;
static void AddMinMaxValue(FuRangeType# target, string name, int value)
{
FuRangeType# type = target.Min == target.Max ? target : new FuRangeType { Min = value, Max = value };
target.Add(new FuConst { Visibility = FuVisibility.Public, Name = name, Value = new FuLiteralLong { Type = type, Value = value }, VisitStatus = FuVisitStatus.Done });
}
public static FuRangeType# New(int min, int max)
{
assert min <= max;
FuRangeType# result = new FuRangeType { Id =
min >= 0 && max <= byte.MaxValue ? FuId.ByteRange :
min >= -128 && max <= 127 ? FuId.SByteRange :
min >= short.MinValue && max <= short.MaxValue ? FuId.ShortRange :
min >= 0 && max <= ushort.MaxValue ? FuId.UShortRange :
FuId.IntType, Min = min, Max = max };
AddMinMaxValue(result, "MinValue", min);
AddMinMaxValue(result, "MaxValue", max);
return result;
}
public override string() ToString() => this.Min == this.Max ? $"{this.Min}" : $"({this.Min} .. {this.Max})";
public override bool IsAssignableFrom(FuType right)
{
switch (right) {
case FuRangeType range:
return this.Min <= range.Max && this.Max >= range.Min;
case FuIntegerType:
return true;
default:
return right.Id == FuId.FloatIntType;
}
}
public override bool EqualsType(FuType right) => right is FuRangeType that && this.Min == that.Min && this.Max == that.Max;
public static int GetMask(int v)
{
// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return v;
}
public int GetVariableBits() => GetMask(this.Min ^ this.Max);
}
class FuFloatingType : FuNumericType
{
public override bool IsAssignableFrom(FuType right) => right is FuNumericType;
}
public abstract class FuNamedValue : FuSymbol
{
internal FuExpr#? TypeExpr;
internal FuExpr#? Value;
public bool IsAssignableStorage() => this.Type is FuStorageType && !(this.Type is FuArrayStorageType)
&& this.Value != null && !(this.Value is FuSymbolReference) && !(this.Value is FuAggregateInitializer);
}
public abstract class FuMember : FuNamedValue
{
internal FuVisibility Visibility;
internal int StartLine;
internal int StartColumn;
internal int EndLine;
internal int EndColumn;
protected FuMember()
{
}
public abstract bool IsStatic();
}
public class FuVar : FuNamedValue
{
internal bool IsAssigned = false;
public static FuVar# New(FuType#? type, string name, FuExpr#? defaultValue = null)
=> new FuVar { Type = type, Name = name, Value = defaultValue };
public override bool IsConst(bool varIsConst) => varIsConst;
public override void Accept(FuVisitor! visitor, FuPriority parent) { visitor.VisitVar(this); }
public FuVar!? NextVar()
{
assert this.Next is FuVar! def; // FIXME: FuVar!?
return def;
}
}
enum FuVisitStatus
{
NotYet,
InProgress,
Done
}
public class FuConst : FuMember
{
internal FuMethodBase? InMethod;
internal int InMethodIndex = 0;
internal FuVisitStatus VisitStatus;
public override bool IsConst(bool VarIsConst) => true;
public override void AcceptStatement(FuVisitor! visitor) { visitor.VisitConst(this); }
public override bool IsStatic() => true;
}
public class FuField : FuMember
{
public override bool IsStatic() => false;
}
class FuProperty : FuMember
{
public override bool IsStatic() => false;
public override bool IsConst(bool varIsConst) => this.Id == FuId.StringLength || this.Id == FuId.ArrayLength;
public static FuProperty# New(FuType# type, FuId id, string name)
=> new FuProperty { Visibility = FuVisibility.Public, Type = type, Id = id, Name = name };
}
class FuStaticProperty : FuMember
{
public override bool IsStatic() => true;
public static FuStaticProperty# New(FuType# type, FuId id, string name)
=> new FuStaticProperty { Visibility = FuVisibility.Public, Type = type, Id = id, Name = name };
}
public class FuThrowsDeclaration : FuSymbolReference
{
internal FuCodeDoc#? Documentation;
}
public class FuMethodBase : FuMember
{
internal FuParameters() Parameters;
internal List<FuThrowsDeclaration#>() Throws;
internal FuScope#? Body;
internal bool IsLive = false;
internal HashSet<FuMethod!>() Calls;
public override bool IsStatic() => false; // constructor
public void AddThis!(FuClass? klass, bool isMutator)
{
FuClassType# type = isMutator ? new FuReadWriteClassType() : new FuClassType();
type.Class = klass;
this.Parameters.Add(FuVar.New(type, "this"));
}
public bool IsMutator() => this.Parameters.First.Type is FuReadWriteClassType;
}
public class FuMethod : FuMethodBase
{
internal FuCallType CallType;
public static FuMethod# New(FuClass? klass, FuVisibility visibility, FuCallType callType, FuType# type, FuId id, string name, bool isMutator, FuVar#? param0 = null, FuVar#? param1 = null, FuVar#? param2 = null, FuVar#? param3 = null)
{
FuMethod# result = new FuMethod { Visibility = visibility, CallType = callType, Type = type, Id = id, Name = name, IsLive = true };
if (callType != FuCallType.Static)
result.AddThis(klass, isMutator);
if (param0 != null) {
result.Parameters.Add(param0);
if (param1 != null) {
result.Parameters.Add(param1);
if (param2 != null) {
result.Parameters.Add(param2);
if (param3 != null)
result.Parameters.Add(param3);
}
}
}
return result;
}
public override bool IsStatic() => this.CallType == FuCallType.Static;
public bool IsAbstractOrVirtual() => this.CallType == FuCallType.Abstract || this.CallType == FuCallType.Virtual;
public bool IsAbstractVirtualOrOverride() => this.CallType == FuCallType.Abstract || this.CallType == FuCallType.Virtual || this.CallType == FuCallType.Override;
public static string CallTypeToString(FuCallType callType)
{
switch (callType) {
case FuCallType.Static: return "static";
case FuCallType.Abstract: return "abstract";
case FuCallType.Virtual: return "virtual";
case FuCallType.Override: return "override";
case FuCallType.Sealed: return "sealed";
default: assert false;
}
}
public FuVar!? FirstParameter()
{
assert this.Parameters.First is FuVar! first; // FIXME: FuVar!?
return IsStatic() ? first : first.NextVar();
}
public int GetParametersCount()
{
int c = this.Parameters.Count();
return IsStatic() ? c : c - 1;
}
public FuMethod GetDeclaringMethod()
{
FuMethod method = this;
while (method.CallType == FuCallType.Override) {
assert method.Parent.Parent.TryLookup(method.Name, false) is FuMethod baseMethod;
method = baseMethod;
}
return method;
}
public bool IsPure()
{
if (!IsStatic())
return false;
for (FuVar? param = this.FirstParameter(); param != null; param = param.NextVar()) {
switch (param.Type) {
case FuNumericType:
case FuEnum:
case FuStringType:
break;
default:
return false;
}
}
return this.Body is FuReturn ret && ret.Value.IsConst(true);
}
}
class FuMethodGroup : FuMember
{
internal FuMethod#?[2] Methods;
FuMethodGroup()
{
}
public override bool IsStatic() { assert false; }
public static FuMethodGroup# New(FuMethod# method0, FuMethod# method1)
{
FuMethodGroup# result = new FuMethodGroup { Visibility = method0.Visibility, Name = method0.Name };
result.Methods[0] = method0;
result.Methods[1] = method1;
return result;
}
}
public abstract class FuContainerType : FuType
{
internal bool IsPublic = false;
internal int StartLine;
internal int StartColumn;
internal int EndLine;
internal int EndColumn;
public override bool IsConst(bool varIsConst) => true;
}
public class FuEnum : FuContainerType
{
internal bool HasExplicitValue = false;
public FuSymbol GetFirstValue()
{
FuSymbol symbol = this.First;
while (!(symbol is FuConst))
symbol = symbol.Next;
return symbol;
}
public void AcceptValues(FuVisitor! visitor)
{
FuConst? previous = null;
for (FuSymbol? symbol = this.First; symbol != null; symbol = symbol.Next) {
if (symbol is FuConst konst) { // not HasFlag
visitor.VisitEnumValue(konst, previous);
previous = konst;
}
}
}
}
class FuEnumFlags : FuEnum
{
}
public class FuClass : FuContainerType
{
internal FuCallType CallType;
internal int TypeParameterCount = 0;
internal bool HasSubclasses = false;
internal FuSymbolReference() BaseClass;
internal FuMethodBase#? Constructor;
internal List<FuConst!>() ConstArrays;
internal SortedSet<string>() CppFriends;
List<FuNative#>() Natives; // FIXME: avoid by moving the ownership from the dictionary to the linked list?
public bool HasBaseClass() => this.BaseClass.Name.Length > 0;
internal void SetBaseClass!(FuClass! baseClass)
{
this.Parent = baseClass;
this.BaseClass.Name = baseClass.Name;
this.BaseClass.Symbol = baseClass;
}
public bool AddsVirtualMethods()
{
for (FuSymbol? symbol = this.First; symbol != null; symbol = symbol.Next) {
if (symbol is FuMethod method && method.IsAbstractOrVirtual())
return true;
}
return false;
}
public static FuClass# New(FuCallType callType, FuId id, string name, int typeParameterCount = 0)
=> new FuClass { CallType = callType, Id = id, Name = name, TypeParameterCount = typeParameterCount };
public void AddMethod!(FuType# type, FuId id, string name, bool isMutator, FuVar#? param0 = null, FuVar#? param1 = null, FuVar#? param2 = null, FuVar#? param3 = null)
{
Add(FuMethod.New(this, FuVisibility.Public, FuCallType.Normal, type, id, name, isMutator, param0, param1, param2, param3));
}
public void AddStaticMethod!(FuType# type, FuId id, string name, FuVar#? param0 = null, FuVar#? param1 = null, FuVar#? param2 = null)
{
Add(FuMethod.New(this, FuVisibility.Public, FuCallType.Static, type, id, name, false, param0, param1, param2));
}
public void AddNative!(FuNative# nat)
{
AddToList(nat);
this.Natives.Add(nat);
}
public bool IsSameOrBaseOf(FuClass derived)
{
while (derived != this) {
if (derived.Parent is FuClass parent)
derived = parent;
else
return false;
}
return true;
}
public FuClass? GetLowestCommonAncestor(FuClass other)
{
for (;;) {
if (other.IsSameOrBaseOf(this))
return other;
if (other.Parent is FuClass parent)
other = parent;
else
return null;
}
}
public bool HasToString() => TryLookup("ToString", false) is FuMethod method && method.Id == FuId.ClassToString;
public bool AddsToString() => this.Dict.ContainsKey("ToString") && this.Dict["ToString"] is FuMethod method && method.Id == FuId.ClassToString
&& method.CallType != FuCallType.Override && method.CallType != FuCallType.Sealed;
}
public class FuClassType : FuType
{
internal FuClass Class;
internal FuType#? TypeArg0;
internal FuType#? TypeArg1;
public FuType# GetElementType() => this.TypeArg0;
public FuType GetKeyType() => this.TypeArg0;
public FuType# GetValueType() => this.TypeArg1;
public override bool IsArray() => this.Class.Id == FuId.ArrayPtrClass || this.Class.Id == FuId.ArrayStorageClass;
public override FuType GetBaseType() => IsArray() ? GetElementType().GetBaseType() : this;
internal bool EqualTypeArguments(FuClassType right)
{
switch (this.Class.TypeParameterCount) {
case 0: return true;
case 1: return this.TypeArg0.EqualsType(right.TypeArg0);
case 2: return this.TypeArg0.EqualsType(right.TypeArg0) && this.TypeArg1.EqualsType(right.TypeArg1);
default: assert false;
}
}
protected bool IsAssignableFromClass(FuClassType right) => this.Class.IsSameOrBaseOf(right.Class) && EqualTypeArguments(right);
public override bool IsAssignableFrom(FuType right)
{
return (this.Nullable && right.Id == FuId.NullType)
|| (right is FuClassType rightClass && IsAssignableFromClass(rightClass));
}
protected bool EqualsTypeInternal(FuClassType that) => this.Nullable == that.Nullable && this.Class == that.Class && EqualTypeArguments(that);
public override bool EqualsType(FuType right)
=> right is FuClassType that && !(right is FuReadWriteClassType) && EqualsTypeInternal(that);
public override string() GetArraySuffix() => IsArray() ? "[]" : "";
public virtual string GetClassSuffix() => "";
string GetNullableSuffix() => this.Nullable ? "?" : "";
public override string() ToString()
{
if (IsArray())
return $"{GetElementType().GetBaseType()}{GetArraySuffix()}{GetNullableSuffix()}{GetElementType().GetArraySuffix()}";
switch (this.Class.TypeParameterCount) {
case 0: return $"{this.Class.Name}{GetClassSuffix()}{GetNullableSuffix()}";
case 1: return $"{this.Class.Name}<{this.TypeArg0}>{GetClassSuffix()}{GetNullableSuffix()}";
case 2: return $"{this.Class.Name}<{this.TypeArg0}, {this.TypeArg1}>{GetClassSuffix()}{GetNullableSuffix()}";
default: assert false;
}
}
}
public class FuReadWriteClassType : FuClassType
{
public override bool IsAssignableFrom(FuType right)
{
return (this.Nullable && right.Id == FuId.NullType)
|| (right is FuReadWriteClassType rightClass && IsAssignableFromClass(rightClass));
}
public override bool EqualsType(FuType right)
=> right is FuReadWriteClassType that && !(right is FuOwningType) && EqualsTypeInternal(that);
public override string() GetArraySuffix() => IsArray() ? "[]!" : "";
public override string GetClassSuffix() => "!";
}
public abstract class FuOwningType : FuReadWriteClassType
{
}
public class FuStorageType : FuOwningType
{
public override bool IsFinal() => this.Class.Id != FuId.MatchClass;
public override bool IsAssignableFrom(FuType right) => right is FuStorageType rightClass && this.Class == rightClass.Class && EqualTypeArguments(rightClass);
public override bool EqualsType(FuType right) => right is FuStorageType that && EqualsTypeInternal(that);
public override string GetClassSuffix() => "()";
}
class FuDynamicPtrType : FuOwningType
{
internal bool Unique = false;
public override bool IsAssignableFrom(FuType right)
{
return (this.Nullable && right.Id == FuId.NullType)
|| (right is FuDynamicPtrType rightClass && IsAssignableFromClass(rightClass));
}
public override bool EqualsType(FuType right) => right is FuDynamicPtrType that && EqualsTypeInternal(that);
public override string() GetArraySuffix() => IsArray() ? "[]#" : "";
public override string GetClassSuffix() => "#";
}
public class FuArrayStorageType : FuStorageType
{
internal FuExpr# LengthExpr;
internal int Length;
internal bool PtrTaken = false;
public override FuType GetBaseType() => GetElementType().GetBaseType();
public override bool IsArray() => true;
public override string() GetArraySuffix() => $"[{this.Length}]";
public override bool EqualsType(FuType right) => right is FuArrayStorageType that && GetElementType().EqualsType(that.GetElementType()) && this.Length == that.Length;
public override FuType GetStorageType() => GetElementType().GetStorageType();
}
class FuStringType : FuClassType
{
public override bool EqualsType(FuType right) => this == right;
}
class FuStringStorageType : FuStringType
{
public override bool IsAssignableFrom(FuType right) => right is FuStringType;
public override string GetClassSuffix() => "()";
}
class FuPrintableType : FuType
{
public override bool IsAssignableFrom(FuType right)
{
switch (right) {
case FuNumericType:
case FuStringType:
return true;
case FuClassType klass:
return klass.Class.HasToString();
default:
return false;
}
}
}
public class FuSystem : FuScope
{
internal FuType# VoidType = new FuType { Id = FuId.VoidType, Name = "void" };
internal FuType# NullType = new FuType { Id = FuId.NullType, Name = "null", Nullable = true };
FuType# TypeParam0 = new FuType { Id = FuId.TypeParam0, Name = "T" };
FuType# TypeParam1 = new FuType { Id = FuId.TypeParam1, Name = "T" };
internal FuIntegerType# IntType = new FuIntegerType { Id = FuId.IntType, Name = "int" };
FuRangeType# UIntType = FuRangeType.New(0, int.MaxValue);
internal FuIntegerType# NIntType = new FuIntegerType { Id = FuId.NIntType, Name = "nint" };
internal FuIntegerType# LongType = new FuIntegerType { Id = FuId.LongType, Name = "long" };
internal FuRangeType# ByteType = FuRangeType.New(0, 0xff);
internal FuFloatingType# FloatType = new FuFloatingType { Id = FuId.FloatType, Name = "float" };
internal FuFloatingType# DoubleType = new FuFloatingType { Id = FuId.DoubleType, Name = "double" };
internal FuRangeType# CharType = FuRangeType.New(-0x80, 0xffff);
internal FuEnum# BoolType = new FuEnum { Id = FuId.BoolType, Name = "bool" };
FuClass# StringClass = FuClass.New(FuCallType.Normal, FuId.StringClass, "string");
internal FuStringType# StringPtrType = new FuStringType { Id = FuId.StringPtrType, Name = "string" };
internal FuStringType# StringNullablePtrType = new FuStringType { Id = FuId.StringPtrType, Name = "string", Nullable = true };
internal FuStringStorageType# StringStorageType = new FuStringStorageType { Id = FuId.StringStorageType };
internal FuType# PrintableType = new FuPrintableType { Name = "printable" };
internal FuClass# ArrayPtrClass = FuClass.New(FuCallType.Normal, FuId.ArrayPtrClass, "ArrayPtr", 1);
internal FuClass# ArrayStorageClass = FuClass.New(FuCallType.Normal, FuId.ArrayStorageClass, "ArrayStorage", 1);
internal FuClass# ExceptionClass = FuClass.New(FuCallType.Normal, FuId.ExceptionClass, "Exception");
internal FuEnum# RegexOptionsEnum;
internal FuReadWriteClassType# LockPtrType = new FuReadWriteClassType();
internal FuClass[9] JsonClasses;
internal FuLiteralLong# NewLiteralLong(long value, int loc = 0)
{
FuType# type = value >= int.MinValue && value <= int.MaxValue ? FuRangeType.New(value, value) : LongType;
return new FuLiteralLong { Loc = loc, Type = type, Value = value };
}
internal FuLiteralString# NewLiteralString(string value, int loc = 0) => new FuLiteralString { Loc = loc, Type = StringPtrType, Value = value };
internal FuType# PromoteIntegerTypes(FuType left, FuType right)
{
return left == LongType || right == LongType ? LongType
: left == NIntType || right == NIntType ? NIntType
: IntType;
}
internal FuType#? PromoteFloatingTypes(FuType left, FuType right)
{
if (left.Id == FuId.DoubleType || right.Id == FuId.DoubleType)
return DoubleType;
if (left.Id == FuId.FloatType || right.Id == FuId.FloatType
|| left.Id == FuId.FloatIntType || right.Id == FuId.FloatIntType)
return FloatType;
return null;
}
internal FuType# PromoteNumericTypes(FuType# left, FuType# right)
{
// TODO: PromoteFloatingTypes(left, right) ?? PromoteIntegerTypes(left, right);
FuType#? result = PromoteFloatingTypes(left, right);
return result != null ? result : PromoteIntegerTypes(left, right);
}
internal FuEnum# NewEnum(bool flags)
{
FuEnum# enu = flags ? new FuEnumFlags() : new FuEnum();
enu.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Static, enu, FuId.EnumFromInt, "FromInt", false, FuVar.New(IntType, "value")));
enu.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, IntType, FuId.EnumToInt, "ToInt", false));
if (flags)
enu.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.EnumHasFlag, "HasFlag", false, FuVar.New(enu, "flag")));
return enu;
}
FuClass! AddCollection!(FuId id, string name, int typeParameterCount, FuId clearId, FuId countId)
{
FuClass# result = FuClass.New(FuCallType.Normal, id, name, typeParameterCount);
result.AddMethod(VoidType, clearId, "Clear", true);
result.Add(FuProperty.New(NIntType, countId, "Count"));
Add(result);
return result;
}
void AddSet!(FuId id, string name, FuId addId, FuId clearId, FuId containsId, FuId countId, FuId removeId)
{
FuClass! set = AddCollection(id, name, 1, clearId, countId);
set.AddMethod(VoidType, addId, "Add", true, FuVar.New(TypeParam0, "value"));
set.AddMethod(BoolType, containsId, "Contains", false, FuVar.New(TypeParam0, "value"));
set.AddMethod(VoidType, removeId, "Remove", true, FuVar.New(TypeParam0, "value"));
}
FuClass AddDictionary!(FuId id, string name, FuId clearId, FuId containsKeyId, FuId countId, FuId removeId)
{
FuClass! dict = AddCollection(id, name, 2, clearId, countId);
dict.Add(FuMethod.New(dict, FuVisibility.FinalValueType, FuCallType.Normal, VoidType, FuId.DictionaryAdd, "Add", true, FuVar.New(TypeParam0, "key")));
dict.AddMethod(BoolType, containsKeyId, "ContainsKey", false, FuVar.New(TypeParam0, "key"));
dict.AddMethod(VoidType, removeId, "Remove", true, FuVar.New(TypeParam0, "key"));
return dict;
}
static void AddEnumValue(FuEnum# enu, FuConst# value)
{
value.Type = enu;
enu.Add(value);
}
FuConst# NewConstLong(string name, long value)
{
FuConst# result = new FuConst { Visibility = FuVisibility.Public, Name = name, Value = NewLiteralLong(value), VisitStatus = FuVisitStatus.Done };
result.Type = result.Value.Type;
return result;
}
FuConst# NewConstDouble(string name, double value)
=> new FuConst { Visibility = FuVisibility.Public, Name = name, Value = new FuLiteralDouble { Value = value, Type = DoubleType }, Type = DoubleType, VisitStatus = FuVisitStatus.Done };
void AddMinMaxValue(FuIntegerType! target, long min, long max)
{
target.Add(NewConstLong("MinValue", min));
target.Add(NewConstLong("MaxValue", max));
}
FuReturn# NewReturnFalse() => new FuReturn { Value = new FuLiteralFalse { Type = BoolType } };
FuReturn# NewReturnTrue() => new FuReturn { Value = new FuLiteralTrue { Type = BoolType } };
FuReturn# NewReturnNull() => new FuReturn { Value = new FuLiteralNull { Type = NullType } };
void AddFalseMethod(FuClass! klass, FuCallType callType, FuId id, string name)
{
FuMethod# method = FuMethod.New(klass, FuVisibility.Public, callType, BoolType, id, name, false);
method.Body = NewReturnFalse();
klass.Add(method);
}
void AddVirtualAssertFalseMethod(FuClass! klass, FuType# type, FuId id, string name)
{
FuMethod# method = FuMethod.New(null, FuVisibility.Public, FuCallType.Virtual, type, id, name, false);
FuBlock# block = new FuBlock();
block.Statements.Add(new FuAssert { Cond = new FuLiteralFalse { Type = BoolType } });
method.Body = block;
klass.Add(method);
}
void AddOverrideTrueMethod(FuClass! klass, string name)
{
FuMethod# method = FuMethod.New(klass, FuVisibility.Public, FuCallType.Override, BoolType, FuId.None, name, false);
method.Body = NewReturnTrue();
klass.Add(method);
}
static FuSymbolReference# NewSymbolReference(FuSymbol! symbol) => new FuSymbolReference { Type = symbol.Type, Name = symbol.Name, Symbol = symbol };
static FuSymbolReference# NewMemberReference(FuSymbolReference# left, FuSymbol! member) => new FuSymbolReference { Left = left, Type = member.Type, Name = member.Name, Symbol = member };
FuCallExpr# NewCall(FuMethod! method) => new FuCallExpr { Type = method.Type, Method = NewSymbolReference(method) };
FuCallExpr# NewMethodCall(FuSymbol! obj, FuMethod! method) => new FuCallExpr { Type = method.Type, Method = NewMemberReference(NewSymbolReference(obj), method) };
void AddJsonGetMethod(FuClass! klass, FuType# type, string name, FuField! valueField)
{
FuMethod# method = FuMethod.New(klass, FuVisibility.Public, FuCallType.Override, type, FuId.None, name, false);
method.Body = new FuReturn { Value = NewSymbolReference(valueField) };
klass.Add(method);
}
FuBinaryExpr# NewOffsetLessInputLength(FuSymbol! offsetField, FuSymbol! inputLengthField)
=> new FuBinaryExpr { Type = BoolType, Left = NewSymbolReference(offsetField), Op = FuToken.Less, Right = NewSymbolReference(inputLengthField) };
FuBinaryExpr# NewInputAtOffset(FuSymbol! inputField, FuSymbol! offsetField)
=> new FuBinaryExpr { Type = IntType, Left = NewSymbolReference(inputField), Op = FuToken.LeftBracket, Right = NewSymbolReference(offsetField) };
void AddCaseCharValue(FuCase! kase, int value)
{
kase.Values.Add(new FuLiteralChar { Type = IntType, Value = value });
}
FuVar# NewDynamicResult(FuClass klass)
{
FuDynamicPtrType# type = new FuDynamicPtrType { Class = klass };
return FuVar.New(type, "result", new FuPrefixExpr { Type = type, Op = FuToken.New, Inner = null });
}
FuCallExpr# NewWriteJsonStringPart(FuField! inputField, FuMethod! stringSubstringMethod, FuVar! startOffsetVar, FuField! offsetField, FuVar! resultVar, FuMethod! textWriterWriteMethod)
{
FuCallExpr# substringCall = NewMethodCall(inputField, stringSubstringMethod);
substringCall.Arguments.Add(NewSymbolReference(startOffsetVar));
substringCall.Arguments.Add(new FuBinaryExpr { Type = NIntType, Left = new FuPostfixExpr { Type = NIntType, Inner = NewSymbolReference(offsetField), Op = FuToken.Increment },
Op = FuToken.Minus, Right = NewSymbolReference(startOffsetVar) });
FuCallExpr# writeCall = NewMethodCall(resultVar, textWriterWriteMethod);
writeCall.Arguments.Add(substringCall);
return writeCall;
}
void AddJsonEscape(FuSwitch! switch2, int c, FuVar! resultVar, FuMethod! textWriterWriteCharMethod, FuLiteralLong# literal)
{
switch2.Cases.Add();
FuCase! kase = switch2.Cases.Last();
AddCaseCharValue(kase, c);
FuCallExpr# call = NewMethodCall(resultVar, textWriterWriteCharMethod);
call.Arguments.Add(literal);
kase.Body.Add(call);
kase.Body.Add(new FuBreak { LoopOrSwitch = switch2 });
}
FuIf# NewIfNotSeeDigitReturnNull(FuMethod! seeDigitMethod)
=> new FuIf { Cond = new FuPrefixExpr { Type = BoolType, Op = FuToken.ExclamationMark, Inner = NewCall(seeDigitMethod) },
OnTrue = NewReturnNull(), OnFalse = null };
void AddParseJsonType(FuSwitch! switch_, int c, FuMethod! method)
{
switch_.Cases.Add();
FuCase! kase = switch_.Cases.Last();
AddCaseCharValue(kase, c);
if (c == '-') {
for (c = '0'; c <= '9'; c++)
AddCaseCharValue(kase, c);
}
kase.Body.Add(new FuReturn { Value = NewCall(method) });
}
void AddParseJsonKeyword(FuSwitch! switch_, string keyword, FuMethod! parseKeywordMethod, FuClass klass)
{
switch_.Cases.Add();
FuCase! kase = switch_.Cases.Last();
AddCaseCharValue(kase, keyword[0]);
FuCallExpr# call = NewCall(parseKeywordMethod);
call.Arguments.Add(NewLiteralString(keyword.Substring(1)));
kase.Body.Add(new FuReturn { Value = new FuSelectExpr { Cond = call,
OnTrue = new FuPrefixExpr { Type = new FuDynamicPtrType { Class = klass }, Op = FuToken.New, Inner = null },
OnFalse = new FuLiteralNull { Type = NullType } } });
}
FuSystem()
{
Parent = null;
FuSymbol# basePtr = FuVar.New(null, "base");
basePtr.Id = FuId.BasePtr;
Add(basePtr);
AddMinMaxValue(IntType, int.MinValue, int.MaxValue);
FuMethod# intTryParseMethod = FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.IntTryParse, "TryParse", true, FuVar.New(StringPtrType, "value"), FuVar.New(IntType, "radix", NewLiteralLong(0)));
IntType.Add(intTryParseMethod);
Add(IntType);
UIntType.Name = "uint";
Add(UIntType);
NIntType.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.NIntTryParse, "TryParse", true, FuVar.New(StringPtrType, "value"), FuVar.New(IntType, "radix", NewLiteralLong(0))));
Add(NIntType);
AddMinMaxValue(LongType, long.MinValue, long.MaxValue);
LongType.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.LongTryParse, "TryParse", true, FuVar.New(StringPtrType, "value"), FuVar.New(IntType, "radix", NewLiteralLong(0))));
Add(LongType);
ByteType.Name = "byte";
Add(ByteType);
FuRangeType# sByteType = FuRangeType.New(-0x80, 0x7f);
sByteType.Name = "sbyte";
Add(sByteType);
FuRangeType# shortType = FuRangeType.New(-0x8000, 0x7fff);
shortType.Name = "short";
Add(shortType);
FuRangeType# ushortType = FuRangeType.New(0, 0xffff);
ushortType.Name = "ushort";
Add(ushortType);
FloatType.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.FloatTryParse, "TryParse", true, FuVar.New(StringPtrType, "value")));
Add(FloatType);
FuMethod# doubleTryParseMethod = FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.DoubleTryParse, "TryParse", true, FuVar.New(StringPtrType, "value"));
DoubleType.Add(doubleTryParseMethod);
Add(DoubleType);
Add(BoolType);
StringClass.AddMethod(BoolType, FuId.StringContains, "Contains", false, FuVar.New(StringPtrType, "value"));
StringClass.AddMethod(BoolType, FuId.StringEndsWith, "EndsWith", false, FuVar.New(StringPtrType, "value"));
StringClass.AddMethod(NIntType, FuId.StringIndexOf, "IndexOf", false, FuVar.New(StringPtrType, "value"));
StringClass.AddMethod(NIntType, FuId.StringLastIndexOf, "LastIndexOf", false, FuVar.New(StringPtrType, "value"));
FuProperty# stringLengthProperty = FuProperty.New(NIntType, FuId.StringLength, "Length");
StringClass.Add(stringLengthProperty);
StringClass.AddMethod(StringStorageType, FuId.StringReplace, "Replace", false, FuVar.New(StringPtrType, "oldValue"), FuVar.New(StringPtrType, "newValue"));
StringClass.AddMethod(BoolType, FuId.StringStartsWith, "StartsWith", false, FuVar.New(StringPtrType, "value"));
FuMethod# stringSubstringMethod = FuMethod.New(StringClass, FuVisibility.Public, FuCallType.Normal, StringStorageType, FuId.StringSubstring, "Substring", false, FuVar.New(NIntType, "offset"), FuVar.New(NIntType, "length", NewLiteralLong(-1)));
StringClass.Add(stringSubstringMethod);
StringClass.AddMethod(StringStorageType, FuId.StringToLower, "ToLower", false);
StringClass.AddMethod(StringStorageType, FuId.StringToUpper, "ToUpper", false);
StringPtrType.Class = StringClass;
Add(StringPtrType);
StringNullablePtrType.Class = StringClass;
StringStorageType.Class = StringClass;
FuMethod# arrayBinarySearchPart = FuMethod.New(null, FuVisibility.NumericElementType, FuCallType.Normal, NIntType, FuId.ArrayBinarySearchPart, "BinarySearch", false,
FuVar.New(TypeParam0, "value"), FuVar.New(NIntType, "startIndex"), FuVar.New(NIntType, "count"));
ArrayPtrClass.Add(arrayBinarySearchPart);
ArrayPtrClass.AddMethod(VoidType, FuId.ArrayCopyTo, "CopyTo", false, FuVar.New(NIntType, "sourceIndex"),
FuVar.New(new FuReadWriteClassType { Class = ArrayPtrClass, TypeArg0 = TypeParam0 }, "destinationArray"), FuVar.New(NIntType, "destinationIndex"), FuVar.New(NIntType, "count"));
FuMethod# arrayFillPart = FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, VoidType, FuId.ArrayFillPart, "Fill", true,
FuVar.New(TypeParam0, "value"), FuVar.New(NIntType, "startIndex"), FuVar.New(NIntType, "count"));
ArrayPtrClass.Add(arrayFillPart);
FuMethod# arraySortPart = FuMethod.New(null, FuVisibility.NumericElementType, FuCallType.Normal, VoidType, FuId.ArraySortPart, "Sort", true, FuVar.New(NIntType, "startIndex"), FuVar.New(NIntType, "count"));
ArrayPtrClass.Add(arraySortPart);
ArrayStorageClass.Parent = ArrayPtrClass;
ArrayStorageClass.Add(FuMethodGroup.New(FuMethod.New(ArrayStorageClass, FuVisibility.NumericElementType, FuCallType.Normal, NIntType, FuId.ArrayBinarySearchAll, "BinarySearch", false, FuVar.New(TypeParam0, "value")),
arrayBinarySearchPart));
ArrayStorageClass.AddMethod(BoolType, FuId.ArrayContains, "Contains", false, FuVar.New(TypeParam0, "value"));
ArrayStorageClass.Add(FuMethodGroup.New(FuMethod.New(ArrayStorageClass, FuVisibility.Public, FuCallType.Normal, VoidType, FuId.ArrayFillAll, "Fill", true, FuVar.New(TypeParam0, "value")),
arrayFillPart));
ArrayStorageClass.Add(FuProperty.New(NIntType, FuId.ArrayLength, "Length"));
ArrayStorageClass.Add(FuMethodGroup.New(
FuMethod.New(ArrayStorageClass, FuVisibility.NumericElementType, FuCallType.Normal, VoidType, FuId.ArraySortAll, "Sort", true),
arraySortPart));
ExceptionClass.IsPublic = true;
Add(ExceptionClass);
FuType# typeParam0NotFinal = new FuType { Id = FuId.TypeParam0NotFinal, Name = "T" };
FuType# typeParam0Predicate = new FuType { Id = FuId.TypeParam0Predicate, Name = "Predicate<T>" };
FuClass! listClass = AddCollection(FuId.ListClass, "List", 1, FuId.ListClear, FuId.ListCount);
FuMethod# listAddMethod = FuMethod.New(listClass, FuVisibility.Public, FuCallType.Normal, VoidType, FuId.ListAdd, "Add", true, FuVar.New(typeParam0NotFinal, "value"));
listClass.Add(listAddMethod);
listClass.AddMethod(VoidType, FuId.ListAddRange, "AddRange", true, FuVar.New(new FuClassType { Class = listClass, TypeArg0 = TypeParam0 }, "source"));
listClass.AddMethod(BoolType, FuId.ListAll, "All", false, FuVar.New(typeParam0Predicate, "predicate"));
listClass.AddMethod(BoolType, FuId.ListAny, "Any", false, FuVar.New(typeParam0Predicate, "predicate"));
listClass.AddMethod(BoolType, FuId.ListContains, "Contains", false, FuVar.New(TypeParam0, "value"));
listClass.AddMethod(VoidType, FuId.ListCopyTo, "CopyTo", false, FuVar.New(NIntType, "sourceIndex"),
FuVar.New(new FuReadWriteClassType { Class = ArrayPtrClass, TypeArg0 = TypeParam0 }, "destinationArray"), FuVar.New(NIntType, "destinationIndex"), FuVar.New(NIntType, "count"));
listClass.AddMethod(NIntType, FuId.ListIndexOf, "IndexOf", false, FuVar.New(TypeParam0, "value"));
listClass.AddMethod(VoidType, FuId.ListInsert, "Insert", true, FuVar.New(NIntType, "index"), FuVar.New(typeParam0NotFinal, "value"));
listClass.AddMethod(TypeParam0, FuId.ListLast, "Last", false);
listClass.AddMethod(VoidType, FuId.ListRemoveAt, "RemoveAt", true, FuVar.New(NIntType, "index"));
listClass.AddMethod(VoidType, FuId.ListRemoveRange, "RemoveRange", true, FuVar.New(NIntType, "index"), FuVar.New(NIntType, "count"));
listClass.Add(FuMethodGroup.New(
FuMethod.New(listClass, FuVisibility.NumericElementType, FuCallType.Normal, VoidType, FuId.ListSortAll, "Sort", true),
FuMethod.New(listClass, FuVisibility.NumericElementType, FuCallType.Normal, VoidType, FuId.ListSortPart, "Sort", true, FuVar.New(NIntType, "startIndex"), FuVar.New(NIntType, "count"))));
FuClass! queueClass = AddCollection(FuId.QueueClass, "Queue", 1, FuId.QueueClear, FuId.QueueCount);
queueClass.AddMethod(TypeParam0, FuId.QueueDequeue, "Dequeue", true);
queueClass.AddMethod(VoidType, FuId.QueueEnqueue, "Enqueue", true, FuVar.New(TypeParam0, "value"));
queueClass.AddMethod(TypeParam0, FuId.QueuePeek, "Peek", false);
FuClass! stackClass = AddCollection(FuId.StackClass, "Stack", 1, FuId.StackClear, FuId.StackCount);
stackClass.AddMethod(TypeParam0, FuId.StackPeek, "Peek", false);
stackClass.AddMethod(VoidType, FuId.StackPush, "Push", true, FuVar.New(TypeParam0, "value"));
stackClass.AddMethod(TypeParam0, FuId.StackPop, "Pop", true);
FuClass! priorityQueueClass = AddCollection(FuId.PriorityQueueClass, "PriorityQueue", 2, FuId.PriorityQueueClear, FuId.PriorityQueueCount);
priorityQueueClass.AddMethod(TypeParam0, FuId.PriorityQueueDequeue, "Dequeue", true);
priorityQueueClass.AddMethod(VoidType, FuId.PriorityQueueEnqueue, "Enqueue", true, FuVar.New(TypeParam0, "element"), FuVar.New(TypeParam1, "priority"));
priorityQueueClass.AddMethod(TypeParam0, FuId.PriorityQueuePeek, "Peek", false);
AddSet(FuId.HashSetClass, "HashSet", FuId.HashSetAdd, FuId.HashSetClear, FuId.HashSetContains, FuId.HashSetCount, FuId.HashSetRemove);
AddSet(FuId.SortedSetClass, "SortedSet", FuId.SortedSetAdd, FuId.SortedSetClear, FuId.SortedSetContains, FuId.SortedSetCount, FuId.SortedSetRemove);
FuClass dictionaryClass = AddDictionary(FuId.DictionaryClass, "Dictionary", FuId.DictionaryClear, FuId.DictionaryContainsKey, FuId.DictionaryCount, FuId.DictionaryRemove);
AddDictionary(FuId.SortedDictionaryClass, "SortedDictionary", FuId.SortedDictionaryClear, FuId.SortedDictionaryContainsKey, FuId.SortedDictionaryCount, FuId.SortedDictionaryRemove);
AddDictionary(FuId.OrderedDictionaryClass, "OrderedDictionary", FuId.OrderedDictionaryClear, FuId.OrderedDictionaryContainsKey, FuId.OrderedDictionaryCount, FuId.OrderedDictionaryRemove);
FuClass# textWriterClass = FuClass.New(FuCallType.Normal, FuId.TextWriterClass, "TextWriter");
textWriterClass.AddMethod(VoidType, FuId.TextWriterFlush, "Flush", true);
FuMethod# textWriterWriteMethod = FuMethod.New(textWriterClass, FuVisibility.Public, FuCallType.Normal, VoidType, FuId.TextWriterWrite, "Write", true, FuVar.New(PrintableType, "value"));
textWriterClass.Add(textWriterWriteMethod);
FuMethod# textWriterWriteCharMethod = FuMethod.New(textWriterClass, FuVisibility.Public, FuCallType.Normal, VoidType, FuId.TextWriterWriteChar, "WriteChar", true, FuVar.New(IntType, "c"));
textWriterClass.Add(textWriterWriteCharMethod);
FuMethod# textWriterWriteCodePointMethod = FuMethod.New(textWriterClass, FuVisibility.Public, FuCallType.Normal, VoidType, FuId.TextWriterWriteCodePoint, "WriteCodePoint", true, FuVar.New(IntType, "c"));
textWriterClass.Add(textWriterWriteCodePointMethod);
textWriterClass.AddMethod(VoidType, FuId.TextWriterWriteLine, "WriteLine", true, FuVar.New(PrintableType, "value", NewLiteralString("")));
Add(textWriterClass);
FuClass# consoleClass = FuClass.New(FuCallType.Static, FuId.None, "Console");
consoleClass.AddStaticMethod(StringStorageType, FuId.ConsoleReadLine, "ReadLine");
consoleClass.AddStaticMethod(VoidType, FuId.ConsoleWrite, "Write", FuVar.New(PrintableType, "value"));
consoleClass.AddStaticMethod(VoidType, FuId.ConsoleWriteLine, "WriteLine", FuVar.New(PrintableType, "value", NewLiteralString("")));
FuStorageType# textWriterStorage = new FuStorageType { Class = textWriterClass };
consoleClass.Add(FuStaticProperty.New(textWriterStorage, FuId.ConsoleError, "Error"));
consoleClass.Add(FuStaticProperty.New(textWriterStorage, FuId.ConsoleOut, "Out"));
Add(consoleClass);
FuClass# stringWriterClass = FuClass.New(FuCallType.Sealed, FuId.StringWriterClass, "StringWriter");
stringWriterClass.AddMethod(VoidType, FuId.StringWriterClear, "Clear", true);
FuMethod# stringWriterToStringMethod = FuMethod.New(stringWriterClass, FuVisibility.Public, FuCallType.Normal, StringPtrType, FuId.StringWriterToString, "ToString", false);
stringWriterClass.Add(stringWriterToStringMethod);
Add(stringWriterClass);
stringWriterClass.Parent = textWriterClass;
FuClass# bitConverterClass = FuClass.New(FuCallType.Static, FuId.None, "BitConverter");
bitConverterClass.AddStaticMethod(FloatType, FuId.BitConverterInt32BitsToSingle, "Int32BitsToSingle", FuVar.New(IntType, "value"));
bitConverterClass.AddStaticMethod(DoubleType, FuId.BitConverterInt64BitsToDouble, "Int64BitsToDouble", FuVar.New(LongType, "value"));
bitConverterClass.AddStaticMethod(IntType, FuId.BitConverterSingleToInt32Bits, "SingleToInt32Bits", FuVar.New(FloatType, "value"));
bitConverterClass.AddStaticMethod(LongType, FuId.BitConverterDoubleToInt64Bits, "DoubleToInt64Bits", FuVar.New(DoubleType, "value"));
Add(bitConverterClass);
FuClass# convertClass = FuClass.New(FuCallType.Static, FuId.None, "Convert");
convertClass.AddStaticMethod(StringStorageType, FuId.ConvertToBase64String, "ToBase64String",
FuVar.New(new FuClassType { Class = ArrayPtrClass, TypeArg0 = ByteType }, "bytes"), FuVar.New(NIntType, "offset"), FuVar.New(NIntType, "length"));
Add(convertClass);
FuClass# utf8EncodingClass = FuClass.New(FuCallType.Sealed, FuId.None, "UTF8Encoding");
utf8EncodingClass.AddMethod(NIntType, FuId.UTF8GetByteCount, "GetByteCount", false, FuVar.New(StringPtrType, "str"));
utf8EncodingClass.AddMethod(VoidType, FuId.UTF8GetBytes, "GetBytes", false,
FuVar.New(StringPtrType, "str"), FuVar.New(new FuReadWriteClassType { Class = ArrayPtrClass, TypeArg0 = ByteType }, "bytes"), FuVar.New(NIntType, "byteIndex"));
utf8EncodingClass.AddMethod(StringStorageType, FuId.UTF8GetString, "GetString", false,
FuVar.New(new FuClassType { Class = ArrayPtrClass, TypeArg0 = ByteType }, "bytes"), FuVar.New(NIntType, "offset"), FuVar.New(NIntType, "length"));
FuClass# encodingClass = FuClass.New(FuCallType.Static, FuId.None, "Encoding");
encodingClass.Add(FuStaticProperty.New(utf8EncodingClass, FuId.None, "UTF8"));
Add(encodingClass);
FuClass# environmentClass = FuClass.New(FuCallType.Static, FuId.None, "Environment");
environmentClass.AddStaticMethod(StringNullablePtrType, FuId.EnvironmentGetEnvironmentVariable, "GetEnvironmentVariable", FuVar.New(StringPtrType, "name"));
Add(environmentClass);
FuClass# dateTimeOffsetClass = FuClass.New(FuCallType.Abstract, FuId.None, "DateTimeOffset");
dateTimeOffsetClass.Add(FuStaticProperty.New(new FuClassType { Class = dateTimeOffsetClass }, FuId.None, "UtcNow"));
dateTimeOffsetClass.AddMethod(LongType, FuId.DateTimeOffsetUtcNowToUnixTimeMilliseconds, "ToUnixTimeMilliseconds", false);
Add(dateTimeOffsetClass);
RegexOptionsEnum = NewEnum(true);
RegexOptionsEnum.IsPublic = true;
RegexOptionsEnum.Id = FuId.RegexOptionsEnum;
RegexOptionsEnum.Name = "RegexOptions";
FuConst# regexOptionsNone = NewConstLong("None", 0);
AddEnumValue(RegexOptionsEnum, regexOptionsNone);
AddEnumValue(RegexOptionsEnum, NewConstLong("IgnoreCase", 1));
AddEnumValue(RegexOptionsEnum, NewConstLong("Multiline", 2));
AddEnumValue(RegexOptionsEnum, NewConstLong("Singleline", 16));
Add(RegexOptionsEnum);
FuClass# regexClass = FuClass.New(FuCallType.Sealed, FuId.RegexClass, "Regex");
regexClass.AddStaticMethod(StringStorageType, FuId.RegexEscape, "Escape", FuVar.New(StringPtrType, "str"));
regexClass.Add(FuMethodGroup.New(
FuMethod.New(null, FuVisibility.Public, FuCallType.Static, BoolType, FuId.RegexIsMatchStr, "IsMatch", false, FuVar.New(StringPtrType, "input"), FuVar.New(StringPtrType, "pattern"), FuVar.New(RegexOptionsEnum, "options", regexOptionsNone)),
FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.RegexIsMatchRegex, "IsMatch", false, FuVar.New(StringPtrType, "input"))));
regexClass.AddStaticMethod(new FuDynamicPtrType { Class = regexClass }, FuId.RegexCompile, "Compile", FuVar.New(StringPtrType, "pattern"), FuVar.New(RegexOptionsEnum, "options", regexOptionsNone));
Add(regexClass);
FuClass# matchClass = FuClass.New(FuCallType.Sealed, FuId.MatchClass, "Match");
matchClass.Add(FuMethodGroup.New(
FuMethod.New(matchClass, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.MatchFindStr, "Find", true, FuVar.New(StringPtrType, "input"), FuVar.New(StringPtrType, "pattern"), FuVar.New(RegexOptionsEnum, "options", regexOptionsNone)),
FuMethod.New(matchClass, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.MatchFindRegex, "Find", true, FuVar.New(StringPtrType, "input"), FuVar.New(new FuClassType { Class = regexClass }, "pattern"))));
matchClass.Add(FuProperty.New(NIntType, FuId.MatchStart, "Start"));
matchClass.Add(FuProperty.New(NIntType, FuId.MatchEnd, "End"));
matchClass.AddMethod(StringStorageType, FuId.MatchGetCapture, "GetCapture", false, FuVar.New(UIntType, "group"));
matchClass.Add(FuProperty.New(NIntType, FuId.MatchLength, "Length"));
matchClass.Add(FuProperty.New(StringStorageType, FuId.MatchValue, "Value"));
Add(matchClass);
FuClass# jsonElementClass = FuClass.New(FuCallType.Abstract, FuId.JsonElementClass, "JsonElement");
FuDynamicPtrType# jsonElementPtr = new FuDynamicPtrType { Class = jsonElementClass };
AddFalseMethod(jsonElementClass, FuCallType.Virtual, FuId.JsonElementIsObject, "IsObject");
AddFalseMethod(jsonElementClass, FuCallType.Virtual, FuId.JsonElementIsArray, "IsArray");
AddFalseMethod(jsonElementClass, FuCallType.Virtual, FuId.JsonElementIsString, "IsString");
AddFalseMethod(jsonElementClass, FuCallType.Virtual, FuId.JsonElementIsNumber, "IsNumber");
AddFalseMethod(jsonElementClass, FuCallType.Virtual, FuId.JsonElementIsBoolean, "IsBoolean");
AddFalseMethod(jsonElementClass, FuCallType.Virtual, FuId.JsonElementIsNull, "IsNull");
AddVirtualAssertFalseMethod(jsonElementClass, new FuClassType { Class = dictionaryClass, TypeArg0 = StringStorageType, TypeArg1 = jsonElementPtr }, FuId.JsonElementGetObject, "GetObject");
AddVirtualAssertFalseMethod(jsonElementClass, new FuClassType { Class = listClass, TypeArg0 = jsonElementPtr }, FuId.JsonElementGetArray, "GetArray");
AddVirtualAssertFalseMethod(jsonElementClass, StringPtrType, FuId.JsonElementGetString, "GetString");
AddVirtualAssertFalseMethod(jsonElementClass, DoubleType, FuId.JsonElementGetDouble, "GetDouble");
AddVirtualAssertFalseMethod(jsonElementClass, BoolType, FuId.JsonElementGetBoolean, "GetBoolean");
FuMethod# jsonElementParseMethod = FuMethod.New(null, FuVisibility.Public, FuCallType.Static, jsonElementPtr, FuId.JsonElementParse, "Parse", false);
FuClass# jsonParserClass = FuClass.New(FuCallType.Sealed, FuId.None, "JsonParser");
FuMethod# jsonParserTryParseMethod = FuMethod.New(null, FuVisibility.Internal, FuCallType.Normal, new FuDynamicPtrType { Nullable = true, Class = jsonElementClass }, FuId.None, "TryParse", true);
{
FuVar# sParam = FuVar.New(StringPtrType, "s");
jsonElementParseMethod.Parameters.Add(sParam);
FuBlock# methodBlock = new FuBlock();
FuVar# parserVar = FuVar.New(new FuStorageType { Class = jsonParserClass }, "parser");
methodBlock.Statements.Add(parserVar);
methodBlock.Add(parserVar);
FuCallExpr# call = NewMethodCall(parserVar, jsonParserTryParseMethod);
call.Arguments.Add(NewSymbolReference(sParam));
methodBlock.Statements.Add(new FuReturn { Value = call });
jsonElementParseMethod.Body = methodBlock;
}
jsonElementClass.Add(jsonElementParseMethod);
Add(jsonElementClass);
JsonClasses[0] = jsonElementClass;
FuClass# jsonObjectClass = FuClass.New(FuCallType.Sealed, FuId.None, "JsonObject");
FuField# jsonObjectValueField = new FuField { Visibility = FuVisibility.Internal, Type = new FuStorageType { Class = dictionaryClass, TypeArg0 = StringStorageType, TypeArg1 = jsonElementPtr }, Name = "Value" };
jsonObjectClass.Add(jsonObjectValueField);
AddOverrideTrueMethod(jsonObjectClass, "IsObject");
AddJsonGetMethod(jsonObjectClass, new FuClassType { Class = dictionaryClass, TypeArg0 = StringStorageType, TypeArg1 = jsonElementPtr }, "GetObject", jsonObjectValueField);
jsonObjectClass.CppFriends.Add("JsonParser");
Add(jsonObjectClass);
jsonObjectClass.SetBaseClass(jsonElementClass);
JsonClasses[1] = jsonObjectClass;
FuClass# jsonArrayClass = FuClass.New(FuCallType.Sealed, FuId.None, "JsonArray");
FuField# jsonArrayValueField = new FuField { Visibility = FuVisibility.Internal, Type = new FuStorageType { Class = listClass, TypeArg0 = jsonElementPtr }, Name = "Value" };
jsonArrayClass.Add(jsonArrayValueField);
AddOverrideTrueMethod(jsonArrayClass, "IsArray");
AddJsonGetMethod(jsonArrayClass, new FuClassType { Class = listClass, TypeArg0 = jsonElementPtr }, "GetArray", jsonArrayValueField);
jsonArrayClass.CppFriends.Add("JsonParser");
Add(jsonArrayClass);
jsonArrayClass.SetBaseClass(jsonElementClass);
JsonClasses[2] = jsonArrayClass;
FuClass# jsonStringClass = FuClass.New(FuCallType.Sealed, FuId.None, "JsonString");
FuField# jsonStringValueField = new FuField { Visibility = FuVisibility.Internal, Type = StringStorageType, Name = "Value" };
jsonStringClass.Add(jsonStringValueField);
AddOverrideTrueMethod(jsonStringClass, "IsString");
AddJsonGetMethod(jsonStringClass, StringPtrType, "GetString", jsonStringValueField);
jsonStringClass.CppFriends.Add("JsonParser");
Add(jsonStringClass);
jsonStringClass.SetBaseClass(jsonElementClass);
JsonClasses[3] = jsonStringClass;
FuClass# jsonNumberClass = FuClass.New(FuCallType.Sealed, FuId.None, "JsonNumber");
FuField# jsonNumberValueField = new FuField { Visibility = FuVisibility.Internal, Type = DoubleType, Name = "Value" };
jsonNumberClass.Add(jsonNumberValueField);
AddOverrideTrueMethod(jsonNumberClass, "IsNumber");
AddJsonGetMethod(jsonNumberClass, DoubleType, "GetDouble", jsonNumberValueField);
jsonNumberClass.CppFriends.Add("JsonParser");
Add(jsonNumberClass);
jsonNumberClass.SetBaseClass(jsonElementClass);
JsonClasses[4] = jsonNumberClass;
FuClass# jsonBooleanClass = FuClass.New(FuCallType.Normal, FuId.None, "JsonBoolean");
AddOverrideTrueMethod(jsonBooleanClass, "IsBoolean");
AddFalseMethod(jsonBooleanClass, FuCallType.Override, FuId.None, "GetBoolean");
Add(jsonBooleanClass);
jsonBooleanClass.SetBaseClass(jsonElementClass);
JsonClasses[5] = jsonBooleanClass;
FuClass# jsonTrueClass = FuClass.New(FuCallType.Sealed, FuId.None, "JsonTrue");
AddOverrideTrueMethod(jsonTrueClass, "GetBoolean");
Add(jsonTrueClass);
jsonTrueClass.SetBaseClass(jsonBooleanClass);
JsonClasses[6] = jsonTrueClass;
FuClass# jsonNullClass = FuClass.New(FuCallType.Sealed, FuId.None, "JsonNull");
AddOverrideTrueMethod(jsonNullClass, "IsNull");
Add(jsonNullClass);
jsonNullClass.SetBaseClass(jsonElementClass);
JsonClasses[7] = jsonNullClass;
FuField# inputField = new FuField { Visibility = FuVisibility.Private, Type = StringPtrType, Name = "Input" };
jsonParserClass.Add(inputField);
FuField# offsetField = new FuField { Visibility = FuVisibility.Private, Type = NIntType, Name = "Offset" };
jsonParserClass.Add(offsetField);
FuField# inputLengthField = new FuField { Visibility = FuVisibility.Private, Type = NIntType, Name = "InputLength" };
jsonParserClass.Add(inputLengthField);
FuMethod# jsonParserSkipWhitespaceMethod = FuMethod.New(jsonParserClass, FuVisibility.Private, FuCallType.Normal, BoolType, FuId.None, "SkipWhitespace", true);
{
FuBlock# methodBlock = new FuBlock();
FuBlock# whileBlock = new FuBlock();
methodBlock.Statements.Add(new FuWhile { Cond = NewOffsetLessInputLength(offsetField, inputLengthField), Body = whileBlock });
FuSwitch# switch_ = new FuSwitch { Value = NewInputAtOffset(inputField, offsetField) };
switch_.Cases.Add();
FuCase! kase = switch_.Cases[0];
AddCaseCharValue(kase, '\t');
AddCaseCharValue(kase, '\n');
AddCaseCharValue(kase, '\r');
AddCaseCharValue(kase, ' ');
kase.Body.Add(new FuBreak { LoopOrSwitch = switch_ });
switch_.DefaultBody.Add(NewReturnTrue());
whileBlock.Statements.Add(switch_);
whileBlock.Statements.Add(new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment });
methodBlock.Statements.Add(new FuReturn { Value = new FuLiteralFalse { Type = BoolType } });
jsonParserSkipWhitespaceMethod.Body = methodBlock;
}
jsonParserClass.Add(jsonParserSkipWhitespaceMethod);
FuMethod# jsonParserParseObjectMethod = FuMethod.New(jsonParserClass, FuVisibility.Private, FuCallType.Normal, new FuDynamicPtrType { Nullable = true, Class = jsonObjectClass }, FuId.None, "ParseObject", true);
FuMethod# jsonParserParseStringMethod = FuMethod.New(jsonParserClass, FuVisibility.Private, FuCallType.Normal, new FuDynamicPtrType { Nullable = true, Class = jsonStringClass }, FuId.None, "ParseString", true);
FuMethod# jsonParserParseWhitespaceAndElementMethod = FuMethod.New(jsonParserClass, FuVisibility.Private, FuCallType.Normal, new FuDynamicPtrType { Nullable = true, Class = jsonElementClass }, FuId.None, "ParseWhitespaceAndElement", true);
{
FuBlock# methodBlock = new FuBlock();
methodBlock.Statements.Add(new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment });
methodBlock.Statements.Add(new FuIf { Cond = new FuPrefixExpr { Type = BoolType, Op = FuToken.ExclamationMark, Inner = NewCall(jsonParserSkipWhitespaceMethod) },
OnTrue = NewReturnNull(), OnFalse = null });
FuVar# resultVar = NewDynamicResult(jsonObjectClass);
methodBlock.Statements.Add(resultVar);
methodBlock.Add(resultVar);
FuBlock# ifBlock = new FuBlock();
methodBlock.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.Equal, Right = new FuLiteralChar { Type = IntType, Value = '}' } },
OnTrue = ifBlock, OnFalse = null });
ifBlock.Statements.Add(new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment });
ifBlock.Statements.Add(new FuReturn { Value = NewSymbolReference(resultVar) });
FuBlock# whileBlock = new FuBlock();
whileBlock.SetCompletesNormally(true);
methodBlock.Statements.Add(new FuWhile { Cond = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.Equal, Right = new FuLiteralChar { Type = IntType, Value = '"' } }, Body = whileBlock });
FuVar# keyVar = FuVar.New(new FuDynamicPtrType { Nullable = true, Class = jsonStringClass }, "key", NewCall(jsonParserParseStringMethod));
whileBlock.Statements.Add(keyVar);
whileBlock.Add(keyVar);
whileBlock.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType, Left = new FuBinaryExpr { Type = BoolType, Left = NewSymbolReference(keyVar), Op = FuToken.Equal, Right = new FuLiteralNull { Type = NullType } },
Op = FuToken.CondOr, Right = new FuBinaryExpr { Type = BoolType, Left = new FuPrefixExpr { Type = BoolType, Op = FuToken.ExclamationMark, Inner = NewCall(jsonParserSkipWhitespaceMethod) },
Op = FuToken.CondOr, Right = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.NotEqual, Right = new FuLiteralChar { Type = IntType, Value = ':' } } } },
OnTrue = NewReturnNull(), OnFalse = null });
whileBlock.Statements.Add(new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment });
FuVar# valueVar = FuVar.New(new FuDynamicPtrType { Nullable = true, Class = jsonElementClass }, "value", NewCall(jsonParserParseWhitespaceAndElementMethod));
whileBlock.Statements.Add(valueVar);
whileBlock.Add(valueVar);
whileBlock.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType, Left = new FuBinaryExpr { Type = BoolType, Left = NewSymbolReference(valueVar), Op = FuToken.Equal, Right = new FuLiteralNull { Type = NullType } },
Op = FuToken.CondOr, Right = new FuPrefixExpr { Type = BoolType, Op = FuToken.ExclamationMark, Inner = NewCall(jsonParserSkipWhitespaceMethod) } },
OnTrue = NewReturnNull(), OnFalse = null });
whileBlock.Statements.Add(new FuBinaryExpr { Type = jsonElementPtr, Left = new FuBinaryExpr { Type = jsonElementPtr, Left = NewMemberReference(NewSymbolReference(resultVar), jsonObjectValueField),
Op = FuToken.LeftBracket, Right = NewMemberReference(NewSymbolReference(keyVar), jsonStringValueField) },
Op = FuToken.Assign, Right = NewSymbolReference(valueVar) });
FuSwitch# switch_ = new FuSwitch { Value = new FuBinaryExpr { Type = IntType, Left = NewSymbolReference(inputField), Op = FuToken.LeftBracket, Right = new FuPostfixExpr { Type = NIntType, Inner = NewSymbolReference(offsetField), Op = FuToken.Increment } } };
switch_.Cases.Add();
AddCaseCharValue(switch_.Cases[0], ',');
switch_.Cases[0].Body.Add(new FuBreak { LoopOrSwitch = switch_ });
switch_.Cases.Add();
AddCaseCharValue(switch_.Cases[1], '}');
switch_.Cases[1].Body.Add(new FuReturn { Value = NewSymbolReference(resultVar) });
switch_.DefaultBody.Add(NewReturnNull());
whileBlock.Statements.Add(switch_);
whileBlock.Statements.Add(new FuIf { Cond = new FuPrefixExpr { Type = BoolType, Op = FuToken.ExclamationMark, Inner = NewCall(jsonParserSkipWhitespaceMethod) },
OnTrue = NewReturnNull(), OnFalse = null });
methodBlock.Statements.Add(NewReturnNull());
jsonParserParseObjectMethod.Body = methodBlock;
}
jsonParserClass.Add(jsonParserParseObjectMethod);
FuMethod# jsonParserParseArrayMethod = FuMethod.New(jsonParserClass, FuVisibility.Private, FuCallType.Normal, new FuDynamicPtrType { Nullable = true, Class = jsonArrayClass }, FuId.None, "ParseArray", true);
FuMethod# jsonParserParseElementMethod = FuMethod.New(jsonParserClass, FuVisibility.Private, FuCallType.Normal, new FuDynamicPtrType { Nullable = true, Class = jsonElementClass }, FuId.None, "ParseElement", true);
{
FuBlock# methodBlock = new FuBlock();
methodBlock.Statements.Add(new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment });
methodBlock.Statements.Add(new FuIf { Cond = new FuPrefixExpr { Type = BoolType, Op = FuToken.ExclamationMark, Inner = NewCall(jsonParserSkipWhitespaceMethod) },
OnTrue = NewReturnNull(), OnFalse = null });
FuVar# resultVar = NewDynamicResult(jsonArrayClass);
methodBlock.Statements.Add(resultVar);
methodBlock.Add(resultVar);
FuBlock# ifBlock = new FuBlock();
methodBlock.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.Equal, Right = new FuLiteralChar { Type = IntType, Value = ']' } },
OnTrue = ifBlock, OnFalse = null });
ifBlock.Statements.Add(new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment });
ifBlock.Statements.Add(new FuReturn { Value = NewSymbolReference(resultVar) });
FuBlock# doWhileBlock = new FuBlock();
doWhileBlock.SetCompletesNormally(true);
methodBlock.Statements.Add(new FuDoWhile { Body = doWhileBlock, Cond = NewCall(jsonParserSkipWhitespaceMethod) });
FuVar# elementVar = FuVar.New(new FuDynamicPtrType { Nullable = true, Class = jsonElementClass }, "element", NewCall(jsonParserParseElementMethod));
doWhileBlock.Statements.Add(elementVar);
doWhileBlock.Add(elementVar);
doWhileBlock.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType, Left = new FuBinaryExpr { Type = BoolType, Left = NewSymbolReference(elementVar), Op = FuToken.Equal, Right = new FuLiteralNull { Type = NullType } },
Op = FuToken.CondOr, Right = new FuPrefixExpr { Type = BoolType, Op = FuToken.ExclamationMark, Inner = NewCall(jsonParserSkipWhitespaceMethod) } },
OnTrue = NewReturnNull(), OnFalse = null });
FuCallExpr# addCall = new FuCallExpr { Type = VoidType, Method = NewMemberReference(NewMemberReference(NewSymbolReference(resultVar), jsonArrayValueField), listAddMethod) };
addCall.Arguments.Add(NewSymbolReference(elementVar));
doWhileBlock.Statements.Add(addCall);
FuSwitch# switch_ = new FuSwitch { Value = new FuBinaryExpr { Type = IntType, Left = NewSymbolReference(inputField), Op = FuToken.LeftBracket, Right = new FuPostfixExpr { Type = NIntType, Inner = NewSymbolReference(offsetField), Op = FuToken.Increment } } };
switch_.Cases.Add();
AddCaseCharValue(switch_.Cases[0], ',');
switch_.Cases[0].Body.Add(new FuBreak { LoopOrSwitch = switch_ });
switch_.Cases.Add();
AddCaseCharValue(switch_.Cases[1], ']');
switch_.Cases[1].Body.Add(new FuReturn { Value = NewSymbolReference(resultVar) });
switch_.DefaultBody.Add(NewReturnNull());
doWhileBlock.Statements.Add(switch_);
methodBlock.Statements.Add(NewReturnNull());
jsonParserParseArrayMethod.Body = methodBlock;
}
jsonParserClass.Add(jsonParserParseArrayMethod);
{
FuBlock# methodBlock = new FuBlock();
methodBlock.Statements.Add(new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment });
FuVar# resultVar = FuVar.New(new FuStorageType { Class = stringWriterClass }, "result");
methodBlock.Statements.Add(resultVar);
methodBlock.Add(resultVar);
FuVar# startOffsetVar = FuVar.New(NIntType, "startOffset", NewSymbolReference(offsetField));
methodBlock.Statements.Add(startOffsetVar);
methodBlock.Add(startOffsetVar);
FuBlock# whileBlock = new FuBlock();
FuWhile# while_ = new FuWhile { Cond = NewOffsetLessInputLength(offsetField, inputLengthField), Body = whileBlock };
FuSwitch# switch_ = new FuSwitch { Value = NewInputAtOffset(inputField, offsetField) };
switch_.Cases.Add();
for (int i = 0; i < 32; i++)
switch_.Cases[0].Values.Add(NewLiteralLong(i));
switch_.Cases[0].Body.Add(NewReturnNull());
switch_.Cases.Add();
AddCaseCharValue(switch_.Cases[1], '"');
switch_.Cases[1].Body.Add(NewWriteJsonStringPart(inputField, stringSubstringMethod, startOffsetVar, offsetField, resultVar, textWriterWriteMethod));
FuAggregateInitializer# init = new FuAggregateInitializer();
init.Items.Add(new FuBinaryExpr { Left = NewSymbolReference(jsonStringValueField), Op = FuToken.Assign, Right = NewMethodCall(resultVar, stringWriterToStringMethod) });
switch_.Cases[1].Body.Add(new FuReturn { Value = new FuPrefixExpr { Type = new FuDynamicPtrType { Class = jsonStringClass }, Op = FuToken.New, Inner = init } });
switch_.Cases.Add();
AddCaseCharValue(switch_.Cases[2], '\\');
switch_.Cases[2].Body.Add(NewWriteJsonStringPart(inputField, stringSubstringMethod, startOffsetVar, offsetField, resultVar, textWriterWriteMethod));
switch_.Cases[2].Body.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType, Left = NewSymbolReference(offsetField), Op = FuToken.GreaterOrEqual, Right = NewSymbolReference(inputLengthField) },
OnTrue = NewReturnNull(), OnFalse = null });
FuSwitch# switch2 = new FuSwitch { Value = NewInputAtOffset(inputField, offsetField) };
switch2.Cases.Add();
AddCaseCharValue(switch2.Cases[0], '"');
AddCaseCharValue(switch2.Cases[0], '\\');
AddCaseCharValue(switch2.Cases[0], '/');
switch2.Cases[0].Body.Add(new FuBinaryExpr { Type = NIntType, Left = NewSymbolReference(startOffsetVar), Op = FuToken.Assign,
Right = new FuPostfixExpr { Type = NIntType, Inner = NewSymbolReference(offsetField), Op = FuToken.Increment } });
switch2.Cases[0].Body.Add(new FuContinue { Loop = while_ });
AddJsonEscape(switch2, 'b', resultVar, textWriterWriteCharMethod, NewLiteralLong(8));
AddJsonEscape(switch2, 'f', resultVar, textWriterWriteCharMethod, NewLiteralLong(12));
AddJsonEscape(switch2, 'n', resultVar, textWriterWriteCharMethod, new FuLiteralChar { Type = IntType, Value = '\n' });
AddJsonEscape(switch2, 'r', resultVar, textWriterWriteCharMethod, new FuLiteralChar { Type = IntType, Value = '\r' });
AddJsonEscape(switch2, 't', resultVar, textWriterWriteCharMethod, new FuLiteralChar { Type = IntType, Value = '\t' });
switch2.Cases.Add();
AddCaseCharValue(switch2.Cases[6], 'u');
switch2.Cases[6].Body.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType, Left = new FuBinaryExpr { Type = NIntType, Left = NewSymbolReference(offsetField), Op = FuToken.Plus, Right = NewLiteralLong(5) },
Op = FuToken.GreaterOrEqual, Right = NewSymbolReference(inputLengthField) },
OnTrue = NewReturnNull(), OnFalse = null });
FuVar# cVar = FuVar.New(IntType, "c");
switch2.Cases[6].Body.Add(cVar);
FuCallExpr# substringCall = NewMethodCall(inputField, stringSubstringMethod);
substringCall.Arguments.Add(new FuBinaryExpr { Type = NIntType, Left = NewSymbolReference(offsetField), Op = FuToken.Plus, Right = NewLiteralLong(1) });
substringCall.Arguments.Add(NewLiteralLong(4));
FuCallExpr# tryParseCall = NewMethodCall(cVar, intTryParseMethod);
tryParseCall.Arguments.Add(substringCall);
tryParseCall.Arguments.Add(NewLiteralLong(16));
switch2.Cases[6].Body.Add(new FuIf { Cond = new FuPrefixExpr { Type = BoolType, Op = FuToken.ExclamationMark, Inner = tryParseCall },
OnTrue = NewReturnNull(), OnFalse = null });
FuCallExpr# writeCodePointCall = NewMethodCall(resultVar, textWriterWriteCodePointMethod);
writeCodePointCall.Arguments.Add(NewSymbolReference(cVar));
switch2.Cases[6].Body.Add(writeCodePointCall);
switch2.Cases[6].Body.Add(new FuBinaryExpr { Left = NewSymbolReference(offsetField), Op = FuToken.AddAssign, Right = NewLiteralLong(4) });
switch2.Cases[6].Body.Add(new FuBreak { LoopOrSwitch = switch2 });
switch2.DefaultBody.Add(NewReturnNull());
switch_.Cases[2].Body.Add(switch2);
switch_.Cases[2].Body.Add(new FuBinaryExpr { Type = NIntType, Left = NewSymbolReference(startOffsetVar), Op = FuToken.Assign,
Right = new FuPrefixExpr { Type = NIntType, Op = FuToken.Increment, Inner = NewSymbolReference(offsetField) } });
switch_.Cases[2].Body.Add(new FuBreak { LoopOrSwitch = switch_ });
switch_.DefaultBody.Add(new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment });
switch_.DefaultBody.Add(new FuBreak { LoopOrSwitch = switch_ });
whileBlock.Statements.Add(switch_);
methodBlock.Statements.Add(while_);
methodBlock.Statements.Add(NewReturnNull());
jsonParserParseStringMethod.Body = methodBlock;
}
jsonParserClass.Add(jsonParserParseStringMethod);
FuMethod# jsonParserSeeDigitMethod = FuMethod.New(jsonParserClass, FuVisibility.Private, FuCallType.Normal, BoolType, FuId.None, "SeeDigit", false);
jsonParserSeeDigitMethod.Body = new FuReturn { Value = new FuBinaryExpr { Type = BoolType, Left = new FuBinaryExpr { Type = BoolType,
Left = NewOffsetLessInputLength(offsetField, inputLengthField), Op = FuToken.CondAnd,
Right = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.GreaterOrEqual, Right = new FuLiteralChar { Type = IntType, Value = '0' } } }, Op = FuToken.CondAnd,
Right = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.LessOrEqual, Right = new FuLiteralChar { Type = IntType, Value = '9' } } } };
jsonParserClass.Add(jsonParserSeeDigitMethod);
FuMethod# jsonParserParseDigitsMethod = FuMethod.New(jsonParserClass, FuVisibility.Private, FuCallType.Normal, VoidType, FuId.None, "ParseDigits", true);
{
FuBlock# methodBlock = new FuBlock();
FuWhile# while_ = new FuWhile { Cond = NewCall(jsonParserSeeDigitMethod), Body = new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment } };
methodBlock.Statements.Add(while_);
jsonParserParseDigitsMethod.Body = methodBlock;
}
jsonParserClass.Add(jsonParserParseDigitsMethod);
FuMethod# jsonParserParseNumberMethod = FuMethod.New(jsonParserClass, FuVisibility.Private, FuCallType.Normal, new FuDynamicPtrType { Nullable = true, Class = jsonNumberClass }, FuId.None, "ParseNumber", true);
{
FuBlock# methodBlock = new FuBlock();
FuVar# startOffsetVar = FuVar.New(NIntType, "startOffset", NewSymbolReference(offsetField));
methodBlock.Statements.Add(startOffsetVar);
methodBlock.Add(startOffsetVar);
methodBlock.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.Equal, Right = new FuLiteralChar { Type = IntType, Value = '-' } },
OnTrue = new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment }, OnFalse = null });
methodBlock.Statements.Add(NewIfNotSeeDigitReturnNull(jsonParserSeeDigitMethod));
methodBlock.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType,
Left = new FuBinaryExpr { Type = IntType, Left = NewSymbolReference(inputField), Op = FuToken.LeftBracket, Right = new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment } },
Op = FuToken.Greater, Right = new FuLiteralChar { Type = IntType, Value = '0' } }, OnTrue = NewCall(jsonParserParseDigitsMethod) });
FuBlock# ifBlock = new FuBlock();
methodBlock.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType,
Left = NewOffsetLessInputLength(offsetField, inputLengthField), Op = FuToken.CondAnd,
Right = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.Equal, Right = new FuLiteralChar { Type = IntType, Value = '.' } } },
OnTrue = ifBlock, OnFalse = null });
ifBlock.Statements.Add(new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment });
ifBlock.Statements.Add(NewIfNotSeeDigitReturnNull(jsonParserSeeDigitMethod));
ifBlock.Statements.Add(NewCall(jsonParserParseDigitsMethod));
FuBlock# if2Block = new FuBlock();
methodBlock.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType,
Left = NewOffsetLessInputLength(offsetField, inputLengthField), Op = FuToken.CondAnd,
Right = new FuBinaryExpr { Type = BoolType, Left = new FuBinaryExpr { Type = IntType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.Or, Right = NewLiteralLong(0x20) },
Op = FuToken.Equal, Right = new FuLiteralChar { Type = IntType, Value = 'e' } } },
OnTrue = if2Block, OnFalse = null });
if2Block.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType,
Left = new FuBinaryExpr { Type = BoolType, Left = new FuPrefixExpr { Type = NIntType, Op = FuToken.Increment, Inner = NewSymbolReference(offsetField) }, Op = FuToken.Less, Right = NewSymbolReference(inputLengthField) },
Op = FuToken.CondAnd, Right = new FuBinaryExpr { Type = BoolType,
Left = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.Equal, Right = new FuLiteralChar { Type = IntType, Value = '+' } },
Op = FuToken.CondOr, Right = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.Equal, Right = new FuLiteralChar { Type = IntType, Value = '-' } } } },
OnTrue = new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment }, OnFalse = null });
if2Block.Statements.Add(NewIfNotSeeDigitReturnNull(jsonParserSeeDigitMethod));
if2Block.Statements.Add(NewCall(jsonParserParseDigitsMethod));
FuVar# dVar = FuVar.New(DoubleType, "d");
methodBlock.Statements.Add(dVar);
methodBlock.Add(dVar);
FuCallExpr# substringCall = NewMethodCall(inputField, stringSubstringMethod);
substringCall.Arguments.Add(NewSymbolReference(startOffsetVar));
substringCall.Arguments.Add(new FuBinaryExpr { Type = NIntType, Left = NewSymbolReference(offsetField), Op = FuToken.Minus, Right = NewSymbolReference(startOffsetVar) });
FuCallExpr# tryParseCall = NewMethodCall(dVar, doubleTryParseMethod);
tryParseCall.Arguments.Add(substringCall);
methodBlock.Statements.Add(new FuIf { Cond = new FuPrefixExpr { Type = BoolType, Op = FuToken.ExclamationMark, Inner = tryParseCall },
OnTrue = NewReturnNull(), OnFalse = null });
FuAggregateInitializer# init = new FuAggregateInitializer();
init.Items.Add(new FuBinaryExpr { Left = NewSymbolReference(jsonNumberValueField), Op = FuToken.Assign, Right = NewSymbolReference(dVar) });
methodBlock.Statements.Add(new FuReturn { Value = new FuPrefixExpr { Type = new FuDynamicPtrType { Class = jsonNumberClass }, Op = FuToken.New, Inner = init } });
jsonParserParseNumberMethod.Body = methodBlock;
}
jsonParserClass.Add(jsonParserParseNumberMethod);
FuVar# sParameter = FuVar.New(StringPtrType, "s");
FuMethod# jsonParserParseKeywordMethod = FuMethod.New(jsonParserClass, FuVisibility.Private, FuCallType.Normal, BoolType, FuId.None, "ParseKeyword", true, sParameter);
{
FuBlock# methodBlock = new FuBlock();
FuBlock# foreachBlock = new FuBlock();
FuForeach# loop = new FuForeach { Collection = NewSymbolReference(sParameter), Body = foreachBlock };
FuVar# cVar = FuVar.New(IntType, "c");
loop.Add(cVar);
foreachBlock.Statements.Add(new FuIf { Cond = new FuBinaryExpr { Type = BoolType,
Left = new FuBinaryExpr { Type = BoolType, Left = new FuPrefixExpr { Type = NIntType, Op = FuToken.Increment, Inner = NewSymbolReference(offsetField) },
Op = FuToken.GreaterOrEqual, Right = NewSymbolReference(inputLengthField) },
Op = FuToken.CondOr, Right = new FuBinaryExpr { Type = BoolType, Left = NewInputAtOffset(inputField, offsetField), Op = FuToken.NotEqual, Right = NewSymbolReference(cVar) } },
OnTrue = NewReturnFalse(), OnFalse = null });
methodBlock.Statements.Add(loop);
methodBlock.Statements.Add(new FuPostfixExpr { Inner = NewSymbolReference(offsetField), Op = FuToken.Increment });
methodBlock.Statements.Add(NewReturnTrue());
jsonParserParseKeywordMethod.Body = methodBlock;
}
jsonParserClass.Add(jsonParserParseKeywordMethod);
{
FuBlock# methodBlock = new FuBlock();
FuSwitch# switch_ = new FuSwitch { Value = NewInputAtOffset(inputField, offsetField) };
AddParseJsonType(switch_, '{', jsonParserParseObjectMethod);
AddParseJsonType(switch_, '[', jsonParserParseArrayMethod);
AddParseJsonType(switch_, '"', jsonParserParseStringMethod);
AddParseJsonType(switch_, '-', jsonParserParseNumberMethod);
AddParseJsonKeyword(switch_, "true", jsonParserParseKeywordMethod, jsonTrueClass);
AddParseJsonKeyword(switch_, "false", jsonParserParseKeywordMethod, jsonBooleanClass);
AddParseJsonKeyword(switch_, "null", jsonParserParseKeywordMethod, jsonNullClass);
switch_.DefaultBody.Add(NewReturnNull());
methodBlock.Statements.Add(switch_);
jsonParserParseElementMethod.Body = methodBlock;
}
jsonParserClass.Add(jsonParserParseElementMethod);
jsonParserParseWhitespaceAndElementMethod.Body = new FuReturn { Value = new FuSelectExpr { Cond = NewCall(jsonParserSkipWhitespaceMethod),
OnTrue = NewCall(jsonParserParseElementMethod), OnFalse = new FuLiteralNull { Type = NullType } } };
jsonParserClass.Add(jsonParserParseWhitespaceAndElementMethod);
{
FuVar# sParam = FuVar.New(StringPtrType, "s");
jsonParserTryParseMethod.Parameters.Add(sParam);
FuBlock# methodBlock = new FuBlock();
methodBlock.Statements.Add(new FuBinaryExpr { Type = StringPtrType, Left = NewSymbolReference(inputField), Op = FuToken.Assign, Right = NewSymbolReference(sParam) });
methodBlock.Statements.Add(new FuBinaryExpr { Type = NIntType, Left = NewSymbolReference(offsetField), Op = FuToken.Assign, Right = NewLiteralLong(0) });
methodBlock.Statements.Add(new FuBinaryExpr { Type = NIntType, Left = NewSymbolReference(inputLengthField), Op = FuToken.Assign, Right = NewMemberReference(NewSymbolReference(sParam), stringLengthProperty) });
FuVar# resultVar = FuVar.New(new FuDynamicPtrType { Nullable = true, Class = jsonElementClass }, "result", NewCall(jsonParserParseWhitespaceAndElementMethod));
methodBlock.Statements.Add(resultVar);
methodBlock.Statements.Add(new FuReturn { Value = new FuSelectExpr { Cond = NewCall(jsonParserSkipWhitespaceMethod),
OnTrue = new FuLiteralNull { Type = NullType }, OnFalse = NewSymbolReference(resultVar) } });
jsonParserTryParseMethod.Body = methodBlock;
}
jsonParserClass.Add(jsonParserTryParseMethod);
jsonParserClass.CppFriends.Add("JsonElement");
Add(jsonParserClass);
JsonClasses[8] = jsonParserClass;
FuNumericType# numericType = new FuNumericType { Id = FuId.NumericType, Name = "numeric" };
FuFloatingType# floatingType = new FuFloatingType { Id = FuId.FloatingType, Name = "float" };
FuFloatingType# floatIntType = new FuFloatingType { Id = FuId.FloatIntType, Name = "float" };
FuClass# mathClass = FuClass.New(FuCallType.Static, FuId.None, "Math");
mathClass.AddStaticMethod(numericType, FuId.MathAbs, "Abs", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Acos", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Asin", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Atan", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Atan2", FuVar.New(DoubleType, "y"), FuVar.New(DoubleType, "x"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Cbrt", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatIntType, FuId.MathCeiling, "Ceiling", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(numericType, FuId.MathClamp, "Clamp", FuVar.New(DoubleType, "value"), FuVar.New(DoubleType, "min"), FuVar.New(DoubleType, "max"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Cos", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Cosh", FuVar.New(DoubleType, "a"));
mathClass.Add(NewConstDouble("E", Math.E));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Exp", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatIntType, FuId.MathMethod, "Floor", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathFusedMultiplyAdd, "FusedMultiplyAdd", FuVar.New(DoubleType, "x"), FuVar.New(DoubleType, "y"), FuVar.New(DoubleType, "z"));
mathClass.AddStaticMethod(BoolType, FuId.MathIsFinite, "IsFinite", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(BoolType, FuId.MathIsInfinity, "IsInfinity", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(BoolType, FuId.MathIsNaN, "IsNaN", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Log", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathLog2, "Log2", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Log10", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(numericType, FuId.MathMax, "Max", FuVar.New(DoubleType, "a"), FuVar.New(DoubleType, "b"));
mathClass.AddStaticMethod(numericType, FuId.MathMin, "Min", FuVar.New(DoubleType, "a"), FuVar.New(DoubleType, "b"));
mathClass.Add(FuStaticProperty.New(FloatType, FuId.MathNaN, "NaN"));
mathClass.Add(FuStaticProperty.New(FloatType, FuId.MathNegativeInfinity, "NegativeInfinity"));
mathClass.Add(NewConstDouble("PI", Math.PI));
mathClass.Add(FuStaticProperty.New(FloatType, FuId.MathPositiveInfinity, "PositiveInfinity"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Pow", FuVar.New(DoubleType, "x"), FuVar.New(DoubleType, "y"));
mathClass.AddStaticMethod(floatIntType, FuId.MathRound, "Round", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Sin", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Sinh", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathSqrt, "Sqrt", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Tan", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Tanh", FuVar.New(DoubleType, "a"));
mathClass.AddStaticMethod(floatIntType, FuId.MathTruncate, "Truncate", FuVar.New(DoubleType, "a"));
Add(mathClass);
FuClass# lockClass = FuClass.New(FuCallType.Sealed, FuId.LockClass, "Lock");
Add(lockClass);
LockPtrType.Class = lockClass;
}
public static FuSystem# New() => new FuSystem();
}
class FuSourceFile
{
internal string() Filename;
internal int Line;
}
public class FuProgram : FuScope
{
internal FuSystem System;
internal List<string()>() TopLevelNatives;
internal List<FuClass!>() Classes;
internal FuMethod? Main = null;
internal SortedDictionary<string(), List<byte>()>() Resources;
internal bool RegexOptionsEnum = false;
internal List<int>() LineLocs;
internal List<FuSourceFile()>() SourceFiles;
public void Init!(FuScope! parent, FuSystem system, FuParserHost! host)
{
this.Parent = parent;
this.System = system;
host.Program = this;
}
internal int GetLine(int loc)
{
int l = 0;
int r = this.LineLocs.Count - 1;
while (l < r) {
int m = l + r + 1 >> 1;
if (loc < this.LineLocs[m])
r = m - 1;
else
l = m;
}
return l;
}
internal FuSourceFile GetSourceFile(int line)
{
int l = 0;
int r = this.SourceFiles.Count - 1;
while (l < r) {
int m = l + r + 1 >> 1;
if (line < this.SourceFiles[m].Line)
r = m - 1;
else
l = m;
}
return this.SourceFiles[l];
}
}