Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 183 additions & 14 deletions GDWeave.Dumper/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,161 @@
using GDWeave.Godot.Variants;

public class CodeGenerator(List<Token> tokens, List<string> identifiers) {
Dictionary<int, string> builtinFunctionLiteral = new() {
[(int) BuiltinFunction.MathSin] = "sin",
[(int) BuiltinFunction.MathCos] = "cos",
[(int) BuiltinFunction.MathTan] = "tan",
[(int) BuiltinFunction.MathSinh] = "sinh",
[(int) BuiltinFunction.MathCosh] = "cosh",
[(int) BuiltinFunction.MathTanh] = "tanh",
[(int) BuiltinFunction.MathAsin] = "asin",
[(int) BuiltinFunction.MathAcos] = "acos",
[(int) BuiltinFunction.MathAtan] = "atan",
[(int) BuiltinFunction.MathAtan2] = "atan2",
[(int) BuiltinFunction.MathSqrt] = "sqrt",
[(int) BuiltinFunction.MathFmod] = "fmod",
[(int) BuiltinFunction.MathFposmod] = "fposmod",
[(int) BuiltinFunction.MathPosmod] = "posmod",
[(int) BuiltinFunction.MathFloor] = "floor",
[(int) BuiltinFunction.MathCeil] = "ceil",
[(int) BuiltinFunction.MathRound] = "round",
[(int) BuiltinFunction.MathAbs] = "abs",
[(int) BuiltinFunction.MathSign] = "sign",
[(int) BuiltinFunction.MathPow] = "pow",
[(int) BuiltinFunction.MathLog] = "log",
[(int) BuiltinFunction.MathExp] = "exp",
[(int) BuiltinFunction.MathIsnan] = "is_nan",
[(int) BuiltinFunction.MathIsinf] = "is_inf",
[(int) BuiltinFunction.MathIsequalapprox] = "is_equal_approx",
[(int) BuiltinFunction.MathIszeroapprox] = "is_zero_approx",
[(int) BuiltinFunction.MathEase] = "ease",
[(int) BuiltinFunction.MathDecimals] = "decimals",
[(int) BuiltinFunction.MathStepDecimals] = "step_decimals",
[(int) BuiltinFunction.MathStepify] = "stepify",
[(int) BuiltinFunction.MathLerp] = "lerp",
[(int) BuiltinFunction.MathLerpAngle] = "lerp_angle",
[(int) BuiltinFunction.MathInverseLerp] = "inverse_lerp",
[(int) BuiltinFunction.MathRangeLerp] = "range_lerp",
[(int) BuiltinFunction.MathSmoothstep] = "smoothstep",
[(int) BuiltinFunction.MathMoveToward] = "move_toward",
[(int) BuiltinFunction.MathDectime] = "dectime",
[(int) BuiltinFunction.MathRandomize] = "randomize",
[(int) BuiltinFunction.MathRand] = "randi",
[(int) BuiltinFunction.MathRandf] = "randf",
[(int) BuiltinFunction.MathRandom] = "rand_range",
[(int) BuiltinFunction.MathSeed] = "seed",
[(int) BuiltinFunction.MathSeed] = "rand_seed",
[(int) BuiltinFunction.MathDeg2Rad] = "deg2rad",
[(int) BuiltinFunction.MathRad2Deg] = "rad2deg",
[(int) BuiltinFunction.MathLinear2Db] = "linear2db",
[(int) BuiltinFunction.MathDb2Linear] = "db2linear",
[(int) BuiltinFunction.MathPolar2Cartesian] = "polar2cartesian",
[(int) BuiltinFunction.MathCartesian2Polar] = "cartesian2polar",
[(int) BuiltinFunction.MathWrap] = "wrapi",
[(int) BuiltinFunction.MathWrap] = "wrapf",
[(int) BuiltinFunction.LogicMax] = "max",
[(int) BuiltinFunction.LogicMin] = "min",
[(int) BuiltinFunction.LogicClamp] = "clamp",
[(int) BuiltinFunction.LogicNearestPo2] = "nearest_po2",
[(int) BuiltinFunction.ObjWeakref] = "weakref",
[(int) BuiltinFunction.FuncFuncref] = "funcref",
[(int) BuiltinFunction.TypeConvert] = "convert",
[(int) BuiltinFunction.TypeOf] = "typeof",
[(int) BuiltinFunction.TypeExists] = "type_exists",
[(int) BuiltinFunction.TextChar] = "char",
[(int) BuiltinFunction.TextOrd] = "ord",
[(int) BuiltinFunction.TextStr] = "str",
[(int) BuiltinFunction.TextPrint] = "print",
[(int) BuiltinFunction.TextPrintTabbed] = "printt",
[(int) BuiltinFunction.TextPrintSpaced] = "prints",
[(int) BuiltinFunction.TextPrinterr] = "printerr",
[(int) BuiltinFunction.TextPrintraw] = "printraw",
[(int) BuiltinFunction.TextPrintDebug] = "print_debug",
[(int) BuiltinFunction.PushError] = "push_error",
[(int) BuiltinFunction.PushWarning] = "push_warning",
[(int) BuiltinFunction.VarToStr] = "var2str",
[(int) BuiltinFunction.StrToVar] = "str2var",
[(int) BuiltinFunction.VarToBytes] = "var2bytes",
[(int) BuiltinFunction.BytesToVar] = "bytes2var",
[(int) BuiltinFunction.GenRange] = "range",
[(int) BuiltinFunction.ResourceLoad] = "load",
[(int) BuiltinFunction.Inst2Dict] = "inst2dict",
[(int) BuiltinFunction.Dict2Inst] = "dict2inst",
[(int) BuiltinFunction.ValidateJson] = "validate_json",
[(int) BuiltinFunction.ParseJson] = "parse_json",
[(int) BuiltinFunction.ToJson] = "to_json",
[(int) BuiltinFunction.Hash] = "hash",
[(int) BuiltinFunction.Color8] = "Color8",
[(int) BuiltinFunction.Colorn] = "ColorN",
[(int) BuiltinFunction.PrintStack] = "print_stack",
[(int) BuiltinFunction.GetStack] = "get_stack",
[(int) BuiltinFunction.InstanceFromId] = "instance_from_id",
[(int) BuiltinFunction.Len] = "len",
[(int) BuiltinFunction.IsInstanceValid] = "is_instance_valid",
[(int) BuiltinFunction.DeepEqual] = "deep_equal",
[(int) BuiltinFunction.FuncMax] = "MAX",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually wasn't sure what function FuncMax is a reference to. Do you remember, @NotNite ?

https://docs.godotengine.org/en/3.5/classes/class_@gdscript.html

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, I believe I copied this enum from the Godot source code; maybe it's unused?

};

public void Generate(StreamWriter writer) {
var onNewLine = false;
var whitespaceExclusions = new List<TokenType>(
[
// Identifiers //
TokenType.BuiltInFunc,
TokenType.PrPreload,
TokenType.BuiltInType,
TokenType.Identifier,
TokenType.Constant,
TokenType.ConstInf,
TokenType.ConstNan,
TokenType.ConstPi,
// Brackets, accessors, etc //
TokenType.BracketOpen,
TokenType.BracketClose,
TokenType.ParenthesisOpen,
TokenType.ParenthesisClose,
TokenType.Period,
TokenType.Dollar,
// Operators, Keywords //
TokenType.OpDiv,
TokenType.OpSub,
TokenType.PrYield,
TokenType.CfElse,
]
);

var binaryOperators = new List<TokenType>(
[
TokenType.OpIn,
TokenType.OpAnd,
TokenType.OpOr,
TokenType.OpEqual,
TokenType.OpGreater,
TokenType.OpGreaterEqual,
TokenType.OpLess,
TokenType.OpLessEqual,
TokenType.OpNotEqual,
TokenType.OpAssign,
TokenType.OpAdd,
// TokenType.OpSub also used for negative numbers
TokenType.OpMul,
// TokenType.OpDiv also used for get_node paths
TokenType.OpMod,
TokenType.OpAssignAdd,
TokenType.OpAssignSub,
TokenType.OpAssignDiv,
TokenType.OpAssignMul,
TokenType.OpAssignMod,
]
);

foreach (var token in tokens) {
var tabs = 0u;
var gen = this.GenerateToken(token, ref tabs);
var onNewLine = gen == "\n";

onNewLine = gen == "\n";

if (!onNewLine)
{
if (binaryOperators.Contains(token.Type)) {
gen = $" {gen} ";
} else if (!onNewLine && !whitespaceExclusions.Contains(token.Type)) {
gen += ' ';
}

Expand All @@ -20,6 +165,17 @@ public void Generate(StreamWriter writer) {
for (var i = 0; i < tabs; i++) {
writer.Write('\t');
}

// If & Else keywords toggle for handling if-else and ternary cases
if (token.Type == TokenType.Newline) {
binaryOperators.Remove(TokenType.CfIf);
binaryOperators.Remove(TokenType.CfElse);
} else {
if (!binaryOperators.Contains(TokenType.CfIf)) {
binaryOperators.Add(TokenType.CfIf);
binaryOperators.Add(TokenType.CfElse);
}
}
}
}

Expand All @@ -31,12 +187,23 @@ private string GenerateToken(Token token, ref uint tabs) {
case TokenType.Identifier:
return $"{identifiers[data]}";
case TokenType.Constant:
var constantToken = (ConstantToken)token;
var constantToken = (ConstantToken) token;
if (
constantToken.Value is StringVariant stringVariant
&& stringVariant.GetValue() is string str
) { return $"\"{str}\""; }
return constantToken.Value.GetValue().ToString() ?? "<Failed to convert to string>";
) {
return $"\"{str}\"";
} else if (constantToken.Value is BoolVariant boolVariant) {
// Lowercase to match GDScript
return (bool) boolVariant.GetValue() ? "true" : "false";
} else if (constantToken.Value is RealVariant realVariant) {
// Refrain from omitting trailing zeros
var value = (double) realVariant.GetValue();
return value.ToString("F");
} else {
return constantToken.Value.GetValue().ToString()
?? "<Failed to convert to string>";
}
case TokenType.Newline:
tabs = token.AssociatedData ?? 0;
return "\n";
Expand All @@ -45,7 +212,9 @@ constantToken.Value is StringVariant stringVariant
case TokenType.BuiltInType:
return Enum.GetName((VariantType) data) ?? "<Invalid builtin type>";
case TokenType.BuiltInFunc:
return Enum.GetName((BuiltinFunction) data) ?? "<Invalid builtin function>";
return builtinFunctionLiteral.ContainsKey(data)
? builtinFunctionLiteral[data]
: "<Invalid builtin function>";
case TokenType.OpIn:
return "in";
case TokenType.OpEqual:
Expand All @@ -61,11 +230,11 @@ constantToken.Value is StringVariant stringVariant
case TokenType.OpGreaterEqual:
return ">=";
case TokenType.OpAnd:
return "&&";
return "and";
case TokenType.OpOr:
return "||";
return "or";
case TokenType.OpNot:
return "!";
return "not";

case TokenType.OpAdd:
return "+";
Expand Down Expand Up @@ -143,13 +312,13 @@ constantToken.Value is StringVariant stringVariant
return "is";

case TokenType.PrOnready:
return "@onready";
return "onready";
case TokenType.PrTool:
return "@tool";
case TokenType.PrStatic:
return "static";
case TokenType.PrExport:
return "@export";
return "export";
// I believe this is incorrect...
// Can't find a good explanation for this token online
case TokenType.PrSetget:
Expand Down
Loading