From 7e49cf1d0a1d1c2cabdb47f6afae28fd30393c61 Mon Sep 17 00:00:00 2001 From: "Tristan B. Kildaire" Date: Thu, 11 Aug 2022 10:26:30 +0200 Subject: [PATCH] Added float support - Added float constant support to the lexer - Added float support to the typechecker to build the correct Instruction type Unit tests - Added unit test for a bad example of a malformed encoded floating point to test out the lexer --- source/tlang/compiler/codegen/instruction.d | 16 +++++ source/tlang/compiler/lexer.d | 64 ++++++++++++++++++- source/tlang/compiler/typecheck/core.d | 33 ++++++++-- .../typecheck/simple_float_constant_bad.t | 4 ++ 4 files changed, 111 insertions(+), 6 deletions(-) create mode 100644 source/tlang/testing/typecheck/simple_float_constant_bad.t diff --git a/source/tlang/compiler/codegen/instruction.d b/source/tlang/compiler/codegen/instruction.d index 8c74730..8564744 100644 --- a/source/tlang/compiler/codegen/instruction.d +++ b/source/tlang/compiler/codegen/instruction.d @@ -95,6 +95,7 @@ public final class FetchValueVar : Value } } +/* Used for integers */ public final class LiteralValue : Value { /* Data */ @@ -110,6 +111,21 @@ public final class LiteralValue : Value } } +public final class LiteralValueFloat : Value +{ + /* Data */ + public double data; /* TODO: Is this best way to store? Consirring floats/doubles */ + public byte len; + + this(double data, byte len) + { + this.data = data; + this.len = len; + + addInfo = "Data: "~to!(string)(data)~", Length: "~to!(string)(len); + } +} + /* FIXME: Implement this */ /** * TODO: This should take in: diff --git a/source/tlang/compiler/lexer.d b/source/tlang/compiler/lexer.d index 4f55105..e20e355 100644 --- a/source/tlang/compiler/lexer.d +++ b/source/tlang/compiler/lexer.d @@ -52,6 +52,7 @@ public final class Lexer private ulong position; /* Current character position */ private char currentChar; /* Current character */ private bool stringMode; /* Whether we are in a string "we are here" or not */ + private bool floatMode; /* Whether or not we are building a floating point constant */ /* The tokens */ private Token[] tokens; @@ -108,7 +109,38 @@ public final class Lexer currentChar = sourceCode[position]; - if(currentChar == ' ' && !stringMode) + if(floatMode == true) + { + if(isDigit(currentChar)) + { + /* tack on and move to next iteration */ + currentToken~=currentChar; + position++; + column++; + continue; + } + /* TODO; handle closer case and error case */ + else + { + /* TODO: Throw erropr here */ + if(isSpliter(currentChar)) + { + floatMode = false; + currentTokens ~= new Token(currentToken, line, column); + currentToken = ""; + + /* We just flush and catch splitter in next round, hence below is commented out */ + // column++; + // position++; + } + else + { + gprintln("Floating point '"~currentToken~"' cannot be followed by a '"~currentChar~"'", DebugType.ERROR); + return false; + } + } + } + else if(currentChar == ' ' && !stringMode) { /* TODO: Check if current token is fulled, then flush */ if(currentToken.length != 0) @@ -128,8 +160,23 @@ public final class Lexer gprintln("Build up: "~currentToken); gprintln("Current char: "~currentChar); + + /* FIXME: Add floating point support here */ /* TODO: IF buildUp is all numerical and we have dot go into float mode */ + /* TODO: Error checking will need to be added */ + if(isNumericalStr(currentToken) && currentChar == '.') + { + /* Tack on the dot */ + currentToken~="."; + + /* Enable floating point mode and go to next iteration*/ + floatMode = true; + gprintln("Halo"); + column++; + position++; + continue; + } /** @@ -536,6 +583,21 @@ public final class Lexer } + private static bool isNumericalStr(string input) + { + for(ulong i = 0; i < input.length; i++) + { + char character = input[i]; + + if(!isDigit(character)) + { + return false; + } + } + + return true; + } + /* Return the tokens */ public Token[] getTokens() diff --git a/source/tlang/compiler/typecheck/core.d b/source/tlang/compiler/typecheck/core.d index 15b1098..e0d9cee 100644 --- a/source/tlang/compiler/typecheck/core.d +++ b/source/tlang/compiler/typecheck/core.d @@ -262,16 +262,39 @@ public final class TypeChecker /** * Typechecking + * + * TODO: Find the type of literal. Integer v.s. floating point */ - gprintln("NUMBER LIT"); - addType(getType(modulle, "int")); + NumberLiteral numLit = cast(NumberLiteral)statement; + import std.string : indexOf; + bool isFloat = indexOf(numLit.getNumber(), ".") > -1; + gprintln("NUMBER LIT: isFloat: "~to!(string)(isFloat)); + addType(getType(modulle, isFloat ? "float" : "int")); /** * Codegen + * + * FIXME: Add support for floats + * TODO: We just assume (for integers) byte size 4? */ - ulong i = to!(ulong)((cast(NumberLiteral)statement).getNumber()); - LiteralValue litValInstr = new LiteralValue(i, 4); - addInstr(litValInstr); + Value valInstr; + + if(!isFloat) + { + ulong i = to!(ulong)((cast(NumberLiteral)statement).getNumber()); + LiteralValue litValInstr = new LiteralValue(i, 4); + + valInstr = litValInstr; + } + else + { + double i = to!(float)((cast(NumberLiteral)statement).getNumber()); + LiteralValueFloat litValInstr = new LiteralValueFloat(i, 4); + + valInstr = litValInstr; + } + + addInstr(valInstr); } /* String literal */ else if(cast(StringExpression)statement) diff --git a/source/tlang/testing/typecheck/simple_float_constant_bad.t b/source/tlang/testing/typecheck/simple_float_constant_bad.t new file mode 100644 index 0000000..0c978fd --- /dev/null +++ b/source/tlang/testing/typecheck/simple_float_constant_bad.t @@ -0,0 +1,4 @@ +module simple; + +float f1 = 1.4d; +double f2 = 1.4f; \ No newline at end of file