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
|
||||
case Expression_Negate:
|
||||
neg := expr.Value.(NegateExpression)
|
||||
case Expression_Unary:
|
||||
unary := expr.Value.(UnaryExpression)
|
||||
exprType := expr.ValueType.Value.(PrimitiveType)
|
||||
|
||||
wat, err := c.compileExpressionWAT(neg.Value)
|
||||
wat, err := c.compileExpressionWAT(unary.Value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
watType := getPrimitiveWATType(exprType)
|
||||
if isSignedInt(exprType) || isUnsignedInt(exprType) {
|
||||
return watType + ".const 0\n" + wat + watType + ".sub\n", nil
|
||||
switch unary.Operation {
|
||||
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:
|
||||
cast := expr.Value.(CastExpression)
|
||||
|
||||
|
@ -6,3 +6,17 @@ u32 c(u32 n) {
|
||||
}
|
||||
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
|
||||
|
||||
var Operators []string = []string{"=", ">", "<", "!", "+", "-", "*", "/", "%", "==", ">=", "<=", "!=", "+=", "-=", "*=", "/=", "%="}
|
||||
var Operators []string = []string{"=", ">", "<", "!", "+", "-", "*", "/", "%", "==", ">=", "<=", "!=", "+=", "-=", "*=", "/=", "%=", "++", "--", "~"}
|
||||
|
||||
const (
|
||||
Operator_Equals Operator = iota
|
||||
@ -76,6 +76,9 @@ const (
|
||||
Operator_MultiplyEquals
|
||||
Operator_DivideEquals
|
||||
Operator_ModuloEquals
|
||||
Operator_PlusPlus
|
||||
Operator_MinusMinus
|
||||
Operator_BitwiseNot
|
||||
)
|
||||
|
||||
type LiteralType uint32
|
||||
|
68
parser.go
68
parser.go
@ -87,7 +87,7 @@ const (
|
||||
Expression_Binary
|
||||
Expression_Tuple
|
||||
Expression_FunctionCall
|
||||
Expression_Negate
|
||||
Expression_Unary
|
||||
Expression_ArrayAccess
|
||||
Expression_RawMemoryReference
|
||||
Expression_Cast
|
||||
@ -125,11 +125,19 @@ const (
|
||||
Operation_Less
|
||||
Operation_GreaterEquals
|
||||
Operation_LessEquals
|
||||
Operation_LogicalNot
|
||||
Operation_NotEquals
|
||||
Operation_Equals
|
||||
)
|
||||
|
||||
type UnaryOperation uint32
|
||||
|
||||
const (
|
||||
UnaryOperation_Negate UnaryOperation = iota
|
||||
UnaryOperation_Nop
|
||||
UnaryOperation_BitwiseNot
|
||||
UnaryOperation_LogicalNot
|
||||
)
|
||||
|
||||
type BinaryExpression struct {
|
||||
Operation Operation
|
||||
Left Expression
|
||||
@ -145,8 +153,9 @@ type FunctionCallExpression struct {
|
||||
Parameters *Expression
|
||||
}
|
||||
|
||||
type NegateExpression struct {
|
||||
Value Expression
|
||||
type UnaryExpression struct {
|
||||
Operation UnaryOperation
|
||||
Value Expression
|
||||
}
|
||||
|
||||
type ArrayAccessExpression struct {
|
||||
@ -594,27 +603,27 @@ func (p *Parser) tryUnaryExpression() (*Expression, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if token.Type == Type_Operator {
|
||||
op := token.Value.(Operator)
|
||||
if op == Operator_Minus || op == Operator_Plus {
|
||||
pCopy.nextToken()
|
||||
expr, err := pCopy.tryPrimaryExpression()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if expr == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if op == Operator_Minus {
|
||||
expr = &Expression{Type: Expression_Negate, Value: NegateExpression{Value: *expr}, Position: token.Position}
|
||||
}
|
||||
|
||||
return expr, nil
|
||||
}
|
||||
op, err := pCopy.tryOperator(Operator_Minus, Operator_Plus, Operator_BitwiseNot, Operator_Not)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if op != nil {
|
||||
expr, err := pCopy.tryPrimaryExpression()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if expr == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
*p = pCopy
|
||||
return &Expression{Type: Expression_Unary, Value: UnaryExpression{Operation: getUnaryOperation(*op), Value: *expr}, Position: token.Position}, nil
|
||||
}
|
||||
|
||||
// TODO: pre-/postfix in-/decrement expr
|
||||
|
||||
return p.tryPrimaryExpression()
|
||||
}
|
||||
|
||||
@ -647,7 +656,12 @@ func (p *Parser) tryBinaryExpression0(opFunc func() (*Expression, error), operat
|
||||
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
|
||||
}
|
||||
|
||||
if lhs == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if lhs.Type != Expression_VariableReference && lhs.Type != Expression_ArrayAccess && lhs.Type != Expression_RawMemoryReference {
|
||||
if lhs == nil || (lhs.Type != Expression_VariableReference && lhs.Type != Expression_ArrayAccess && lhs.Type != Expression_RawMemoryReference) {
|
||||
return p.tryBinaryExpression()
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
module alloc;
|
||||
|
||||
u64 alloc(u64 size) {
|
||||
u64 ptr = 0x0u64;
|
||||
raw(i32, ptr) = 0x03u32;
|
||||
i32 sus = raw(i32, ptr);
|
||||
return 0u64;
|
||||
}
|
||||
|
||||
|
19
types.go
19
types.go
@ -154,8 +154,6 @@ func getOperation(operator Operator) Operation {
|
||||
return Operation_Greater
|
||||
case Operator_Less:
|
||||
return Operation_Less
|
||||
case Operator_Not:
|
||||
return Operation_LogicalNot
|
||||
case Operator_Plus, Operator_PlusEquals:
|
||||
return Operation_Add
|
||||
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 {
|
||||
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
|
||||
default:
|
||||
return false
|
||||
|
30
validator.go
30
validator.go
@ -156,7 +156,7 @@ func (v *Validator) getArithmeticResultType(expr *Expression, left PrimitiveType
|
||||
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 {
|
||||
@ -324,24 +324,36 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression) []error
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: get function and validate using return type
|
||||
expr.ValueType = calledFunc.ReturnType
|
||||
expr.Value = fc
|
||||
case Expression_Negate:
|
||||
neg := expr.Value.(NegateExpression)
|
||||
case Expression_Unary:
|
||||
unary := expr.Value.(UnaryExpression)
|
||||
|
||||
valErrors := v.validateExpression(&neg.Value)
|
||||
valErrors := v.validateExpression(&unary.Value)
|
||||
if len(valErrors) != 0 {
|
||||
errors = append(errors, valErrors...)
|
||||
return errors
|
||||
}
|
||||
|
||||
if neg.Value.ValueType.Type != Type_Primitive {
|
||||
errors = append(errors, v.createError("cannot negate non-number types", expr.Position))
|
||||
if unary.Value.ValueType.Type != Type_Primitive {
|
||||
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))
|
||||
}
|
||||
|
||||
if unary.Operation == UnaryOperation_LogicalNot && primitive != Primitive_Bool {
|
||||
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 = neg.Value.ValueType
|
||||
expr.Value = neg
|
||||
expr.ValueType = unary.Value.ValueType
|
||||
expr.Value = unary
|
||||
case Expression_RawMemoryReference:
|
||||
raw := expr.Value.(RawMemoryReferenceExpression)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user