added support for floats

This commit is contained in:
Andrew Segavac
2021-05-29 10:50:15 -06:00
parent b8769f43e3
commit 374e080f26
4 changed files with 46 additions and 12 deletions

View File

@@ -62,6 +62,12 @@ class LiteralInt:
type: TypeUsage
@dataclass
class LiteralFloat:
value: float
type: TypeUsage
@dataclass
class FunctionCall:
source: "Expression"
@@ -85,7 +91,7 @@ class VariableUsage:
@dataclass
class Expression:
expression: Union[LiteralInt, FunctionCall, VariableUsage, Operation]
expression: Union[LiteralInt, LiteralFloat, FunctionCall, VariableUsage, Operation]
type: TypeUsage
@@ -131,8 +137,9 @@ boring_grammar = r"""
mult : "*"
div : "/"
literal_int: SIGNED_NUMBER
identifier : NAME
literal_float : SIGNED_FLOAT
literal_int : SIGNED_INT
identifier : CNAME
function_call : expression "(" [expression ("," expression)*] ")"
@@ -152,6 +159,7 @@ boring_grammar = r"""
| term
term : literal_int
| literal_float
| variable_usage
| function_call
| "(" expression ")"
@@ -185,8 +193,9 @@ boring_grammar = r"""
module : (function)*
%import common.CNAME -> NAME
%import common.SIGNED_NUMBER
%import common.CNAME
%import common.SIGNED_INT
%import common.SIGNED_FLOAT
%import common.WS
%ignore WS
"""
@@ -214,6 +223,10 @@ class TreeToBoring(Transformer):
(n,) = n
return LiteralInt(value=int(n), type=UnknownTypeUsage())
def literal_float(self, f) -> LiteralFloat:
(f,) = f
return LiteralFloat(value=float(f), type=UnknownTypeUsage())
def identifier(self, i) -> str:
(i,) = i
return str(i)

View File

@@ -131,6 +131,10 @@ class TypeChecker:
if self.with_literal_int(env, type_env, subexpression):
changed = True
return changed
if isinstance(subexpression, parse.LiteralFloat):
if self.with_literal_float(env, type_env, subexpression):
changed = True
return changed
if isinstance(subexpression, parse.FunctionCall):
if self.with_function_call(env, type_env, subexpression):
changed = True
@@ -198,11 +202,14 @@ class TypeChecker:
changed = True
return changed
def with_literal_int(self, env: Environment, type_env: TypeEnvironment, literal_int: parse.LiteralInt) -> bool:
ints = [
parse.DataTypeUsage(name=name)
for name in ["I8", "I16", "I32", "I64", "I128"]
]
if not isinstance(literal_int.type, parse.UnknownTypeUsage):
assert literal_int.type in ints, f"{literal_int.type}"
def with_literal_float(self, env: Environment, type_env: TypeEnvironment, literal_float: parse.LiteralFloat) -> bool:
floats = ["F32", "F64", "F128"]
if not isinstance(literal_float.type, parse.UnknownTypeUsage):
assert literal_float.type.name in floats, f"{literal_float.type}"
return False
def with_literal_int(self, env: Environment, type_env: TypeEnvironment, literal_int: parse.LiteralInt) -> bool:
ints = ["I8", "I16", "I32", "I64", "I128", "U8", "U16", "U32", "U64", "U128"]
if not isinstance(literal_int.type, parse.UnknownTypeUsage):
assert literal_int.type.name in ints, f"{literal_int.type}"
return False

View File

@@ -1,5 +1,6 @@
fn add(a: I32, b: I32): I32 {
let foo = 4;
let test_float: F32 = 10.2;
a + b + foo
}

View File

@@ -26,3 +26,16 @@ class TypeUsage:
result: Identifier # Result of useage - either is the type, or is the return value if it's a function
type_args: List[Type] # Generics
arguments: Optional[List[Type]] # Specified if it is a function, this is how you tell if it's a function
TODO:
* ~Float Literals~
* Block expression
* Return keyword
* Structs
* Generics
* Enums
* Methods
* Traits
* Async