More unary expressions
This commit is contained in:
parent
45f5ea3398
commit
0236dfbb2d
@ -323,23 +323,35 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return wat + "call $" + fc.Function + "\n", nil
|
return wat + "call $" + fc.Function + "\n", nil
|
||||||
case Expression_Negate:
|
case Expression_Unary:
|
||||||
neg := expr.Value.(NegateExpression)
|
unary := expr.Value.(UnaryExpression)
|
||||||
exprType := expr.ValueType.Value.(PrimitiveType)
|
exprType := expr.ValueType.Value.(PrimitiveType)
|
||||||
|
|
||||||
wat, err := c.compileExpressionWAT(neg.Value)
|
wat, err := c.compileExpressionWAT(unary.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
watType := getPrimitiveWATType(exprType)
|
watType := getPrimitiveWATType(exprType)
|
||||||
if isSignedInt(exprType) || isUnsignedInt(exprType) {
|
switch unary.Operation {
|
||||||
return watType + ".const 0\n" + wat + watType + ".sub\n", nil
|
case UnaryOperation_Negate:
|
||||||
|
if isFloatingPoint(exprType) {
|
||||||
|
return wat + watType + ".neg\n", nil
|
||||||
|
} else {
|
||||||
|
return watType + ".const 0\n" + wat + watType + ".sub\n" + getTypeCast(exprType), nil
|
||||||
|
}
|
||||||
|
case UnaryOperation_Nop:
|
||||||
|
return wat, nil
|
||||||
|
case UnaryOperation_BitwiseNot:
|
||||||
|
if getBits(exprType) == 64 {
|
||||||
|
return wat + watType + ".const 0xFFFFFFFFFFFFFFFF\n" + watType + ".xor\n" + getTypeCast(exprType), nil
|
||||||
|
} else {
|
||||||
|
return wat + watType + ".const 0xFFFFFFFF\n" + watType + ".xor\n" + getTypeCast(exprType), nil
|
||||||
|
}
|
||||||
|
case UnaryOperation_LogicalNot:
|
||||||
|
return wat + "i32.eqz\n", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if isFloatingPoint(exprType) {
|
|
||||||
return watType + ".neg\n", nil
|
|
||||||
}
|
|
||||||
case Expression_Cast:
|
case Expression_Cast:
|
||||||
cast := expr.Value.(CastExpression)
|
cast := expr.Value.(CastExpression)
|
||||||
|
|
||||||
|
@ -6,3 +6,17 @@ u32 c(u32 n) {
|
|||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u64 fib(u64 i) {
|
||||||
|
u64 fibA = 0u64;
|
||||||
|
u64 fibB = 1u64;
|
||||||
|
|
||||||
|
while((i -= 1u64) > 0u64) {
|
||||||
|
u64 tmp = fibB;
|
||||||
|
fibB = fibA + fibB;
|
||||||
|
fibA = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fibA;
|
||||||
|
}
|
||||||
|
5
lexer.go
5
lexer.go
@ -55,7 +55,7 @@ const (
|
|||||||
|
|
||||||
type Operator uint32
|
type Operator uint32
|
||||||
|
|
||||||
var Operators []string = []string{"=", ">", "<", "!", "+", "-", "*", "/", "%", "==", ">=", "<=", "!=", "+=", "-=", "*=", "/=", "%="}
|
var Operators []string = []string{"=", ">", "<", "!", "+", "-", "*", "/", "%", "==", ">=", "<=", "!=", "+=", "-=", "*=", "/=", "%=", "++", "--", "~"}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Operator_Equals Operator = iota
|
Operator_Equals Operator = iota
|
||||||
@ -76,6 +76,9 @@ const (
|
|||||||
Operator_MultiplyEquals
|
Operator_MultiplyEquals
|
||||||
Operator_DivideEquals
|
Operator_DivideEquals
|
||||||
Operator_ModuloEquals
|
Operator_ModuloEquals
|
||||||
|
Operator_PlusPlus
|
||||||
|
Operator_MinusMinus
|
||||||
|
Operator_BitwiseNot
|
||||||
)
|
)
|
||||||
|
|
||||||
type LiteralType uint32
|
type LiteralType uint32
|
||||||
|
46
parser.go
46
parser.go
@ -87,7 +87,7 @@ const (
|
|||||||
Expression_Binary
|
Expression_Binary
|
||||||
Expression_Tuple
|
Expression_Tuple
|
||||||
Expression_FunctionCall
|
Expression_FunctionCall
|
||||||
Expression_Negate
|
Expression_Unary
|
||||||
Expression_ArrayAccess
|
Expression_ArrayAccess
|
||||||
Expression_RawMemoryReference
|
Expression_RawMemoryReference
|
||||||
Expression_Cast
|
Expression_Cast
|
||||||
@ -125,11 +125,19 @@ const (
|
|||||||
Operation_Less
|
Operation_Less
|
||||||
Operation_GreaterEquals
|
Operation_GreaterEquals
|
||||||
Operation_LessEquals
|
Operation_LessEquals
|
||||||
Operation_LogicalNot
|
|
||||||
Operation_NotEquals
|
Operation_NotEquals
|
||||||
Operation_Equals
|
Operation_Equals
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type UnaryOperation uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
UnaryOperation_Negate UnaryOperation = iota
|
||||||
|
UnaryOperation_Nop
|
||||||
|
UnaryOperation_BitwiseNot
|
||||||
|
UnaryOperation_LogicalNot
|
||||||
|
)
|
||||||
|
|
||||||
type BinaryExpression struct {
|
type BinaryExpression struct {
|
||||||
Operation Operation
|
Operation Operation
|
||||||
Left Expression
|
Left Expression
|
||||||
@ -145,7 +153,8 @@ type FunctionCallExpression struct {
|
|||||||
Parameters *Expression
|
Parameters *Expression
|
||||||
}
|
}
|
||||||
|
|
||||||
type NegateExpression struct {
|
type UnaryExpression struct {
|
||||||
|
Operation UnaryOperation
|
||||||
Value Expression
|
Value Expression
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,10 +603,12 @@ func (p *Parser) tryUnaryExpression() (*Expression, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if token.Type == Type_Operator {
|
op, err := pCopy.tryOperator(Operator_Minus, Operator_Plus, Operator_BitwiseNot, Operator_Not)
|
||||||
op := token.Value.(Operator)
|
if err != nil {
|
||||||
if op == Operator_Minus || op == Operator_Plus {
|
return nil, err
|
||||||
pCopy.nextToken()
|
}
|
||||||
|
|
||||||
|
if op != nil {
|
||||||
expr, err := pCopy.tryPrimaryExpression()
|
expr, err := pCopy.tryPrimaryExpression()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -607,13 +618,11 @@ func (p *Parser) tryUnaryExpression() (*Expression, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if op == Operator_Minus {
|
*p = pCopy
|
||||||
expr = &Expression{Type: Expression_Negate, Value: NegateExpression{Value: *expr}, Position: token.Position}
|
return &Expression{Type: Expression_Unary, Value: UnaryExpression{Operation: getUnaryOperation(*op), Value: *expr}, Position: token.Position}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return expr, nil
|
// TODO: pre-/postfix in-/decrement expr
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.tryPrimaryExpression()
|
return p.tryPrimaryExpression()
|
||||||
}
|
}
|
||||||
@ -647,7 +656,12 @@ func (p *Parser) tryBinaryExpression0(opFunc func() (*Expression, error), operat
|
|||||||
return nil, p.error("expected expression")
|
return nil, p.error("expected expression")
|
||||||
}
|
}
|
||||||
|
|
||||||
left = &Expression{Type: Expression_Binary, Value: BinaryExpression{Operation: getOperation(*op), Left: *left, Right: *right}, Position: left.Position}
|
operation := getOperation(*op)
|
||||||
|
if operation == InvalidValue {
|
||||||
|
return nil, p.error("operator not allowed in binary expression")
|
||||||
|
}
|
||||||
|
|
||||||
|
left = &Expression{Type: Expression_Binary, Value: BinaryExpression{Operation: operation, Left: *left, Right: *right}, Position: left.Position}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,11 +693,7 @@ func (p *Parser) tryAssignmentExpression() (*Expression, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if lhs == nil {
|
if lhs == nil || (lhs.Type != Expression_VariableReference && lhs.Type != Expression_ArrayAccess && lhs.Type != Expression_RawMemoryReference) {
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if lhs.Type != Expression_VariableReference && lhs.Type != Expression_ArrayAccess && lhs.Type != Expression_RawMemoryReference {
|
|
||||||
return p.tryBinaryExpression()
|
return p.tryBinaryExpression()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
module alloc;
|
module alloc;
|
||||||
|
|
||||||
u64 alloc(u64 size) {
|
u64 alloc(u64 size) {
|
||||||
u64 ptr = 0x0u64;
|
|
||||||
raw(i32, ptr) = 0x03u32;
|
|
||||||
i32 sus = raw(i32, ptr);
|
|
||||||
return 0u64;
|
return 0u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
types.go
19
types.go
@ -154,8 +154,6 @@ func getOperation(operator Operator) Operation {
|
|||||||
return Operation_Greater
|
return Operation_Greater
|
||||||
case Operator_Less:
|
case Operator_Less:
|
||||||
return Operation_Less
|
return Operation_Less
|
||||||
case Operator_Not:
|
|
||||||
return Operation_LogicalNot
|
|
||||||
case Operator_Plus, Operator_PlusEquals:
|
case Operator_Plus, Operator_PlusEquals:
|
||||||
return Operation_Add
|
return Operation_Add
|
||||||
case Operator_Minus, Operator_MinusEquals:
|
case Operator_Minus, Operator_MinusEquals:
|
||||||
@ -179,9 +177,24 @@ func getOperation(operator Operator) Operation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getUnaryOperation(operator Operator) UnaryOperation {
|
||||||
|
switch operator {
|
||||||
|
case Operator_Minus:
|
||||||
|
return UnaryOperation_Negate
|
||||||
|
case Operator_Plus:
|
||||||
|
return UnaryOperation_Nop
|
||||||
|
case Operator_BitwiseNot:
|
||||||
|
return UnaryOperation_BitwiseNot
|
||||||
|
case Operator_Not:
|
||||||
|
return UnaryOperation_LogicalNot
|
||||||
|
default:
|
||||||
|
return InvalidValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func isBooleanOperation(operation Operation) bool {
|
func isBooleanOperation(operation Operation) bool {
|
||||||
switch operation {
|
switch operation {
|
||||||
case Operation_Greater, Operation_Less, Operation_LogicalNot, Operation_Equals, Operation_GreaterEquals, Operation_LessEquals, Operation_NotEquals:
|
case Operation_Greater, Operation_Less, Operation_Equals, Operation_GreaterEquals, Operation_LessEquals, Operation_NotEquals:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
30
validator.go
30
validator.go
@ -156,7 +156,7 @@ func (v *Validator) getArithmeticResultType(expr *Expression, left PrimitiveType
|
|||||||
return left, nil
|
return left, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return InvalidValue, v.createError(fmt.Sprintf("cannot use the types [%s, %s] in an arithmetic expression without an explicit cast", left, right), expr.Position) // TODO: include type names in error
|
return InvalidValue, v.createError(fmt.Sprintf("cannot use the types [%s, %s] in an arithmetic expression without an explicit cast", left, right), expr.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLocal(block *Block, variable string) *Local {
|
func getLocal(block *Block, variable string) *Local {
|
||||||
@ -324,24 +324,36 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression) []error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: get function and validate using return type
|
|
||||||
expr.ValueType = calledFunc.ReturnType
|
expr.ValueType = calledFunc.ReturnType
|
||||||
expr.Value = fc
|
expr.Value = fc
|
||||||
case Expression_Negate:
|
case Expression_Unary:
|
||||||
neg := expr.Value.(NegateExpression)
|
unary := expr.Value.(UnaryExpression)
|
||||||
|
|
||||||
valErrors := v.validateExpression(&neg.Value)
|
valErrors := v.validateExpression(&unary.Value)
|
||||||
if len(valErrors) != 0 {
|
if len(valErrors) != 0 {
|
||||||
errors = append(errors, valErrors...)
|
errors = append(errors, valErrors...)
|
||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
if neg.Value.ValueType.Type != Type_Primitive {
|
if unary.Value.ValueType.Type != Type_Primitive {
|
||||||
errors = append(errors, v.createError("cannot negate non-number types", expr.Position))
|
errors = append(errors, v.createError("cannot operate on non-primitive types", expr.Position))
|
||||||
|
} else {
|
||||||
|
primitive := unary.Value.ValueType.Value.(PrimitiveType)
|
||||||
|
if (unary.Operation == UnaryOperation_Negate || unary.Operation == UnaryOperation_Nop /* + sign */) && !isSignedInt(primitive) && !isFloatingPoint(primitive) {
|
||||||
|
errors = append(errors, v.createError("can only perform negation/unary plus on signed types", expr.Position))
|
||||||
}
|
}
|
||||||
|
|
||||||
expr.ValueType = neg.Value.ValueType
|
if unary.Operation == UnaryOperation_LogicalNot && primitive != Primitive_Bool {
|
||||||
expr.Value = neg
|
errors = append(errors, v.createError("cannot perform logical not on non-bool type", expr.Position))
|
||||||
|
}
|
||||||
|
|
||||||
|
if unary.Operation == UnaryOperation_BitwiseNot && !isUnsignedInt(primitive) && !isSignedInt(primitive) {
|
||||||
|
errors = append(errors, v.createError("cannot perform bitwise not on non-integer type", expr.Position))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expr.ValueType = unary.Value.ValueType
|
||||||
|
expr.Value = unary
|
||||||
case Expression_RawMemoryReference:
|
case Expression_RawMemoryReference:
|
||||||
raw := expr.Value.(RawMemoryReferenceExpression)
|
raw := expr.Value.(RawMemoryReferenceExpression)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user