Parse array types, Fix compiler errors

This commit is contained in:
MrLetsplay 2024-03-28 18:20:52 +01:00
parent aef95b74cc
commit 99372dbc6a
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
3 changed files with 76 additions and 18 deletions

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
@ -35,13 +36,15 @@ const (
type Separator uint32 type Separator uint32
var Separators []rune = []rune{'(', ')', '{', '}', ';', ','} var Separators []rune = []rune{'(', ')', '{', '}', '[', ']', ';', ','}
const ( const (
Separator_OpenParen Separator = iota Separator_OpenParen Separator = iota
Separator_CloseParen Separator_CloseParen
Separator_OpenCurly Separator_OpenCurly
Separator_CloseCurly Separator_CloseCurly
Separator_OpenSquare
Separator_CloseSquare
Separator_Semicolon Separator_Semicolon
Separator_Comma Separator_Comma
) )
@ -260,7 +263,7 @@ func (l *Lexer) nextToken() (*LexToken, error) {
return nil, l.error("dot in non floating-point constant") return nil, l.error("dot in non floating-point constant")
} }
number, err := parseNumber(rawNumber, numberType) number, err := l.parseNumber(rawNumber, numberType)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -281,21 +284,55 @@ func (l *Lexer) nextToken() (*LexToken, error) {
return &LexToken{Type: Type_Identifier, Position: l.LastTokenPosition, Value: token}, nil return &LexToken{Type: Type_Identifier, Position: l.LastTokenPosition, Value: token}, nil
} }
func parseNumber(raw string, numberType PrimitiveType) (any, error) { func (l *Lexer) parseNumber(raw string, numberType PrimitiveType) (any, error) {
// TODO: return compiler errors if numberType == Primitive_Bool {
return nil, l.error("bool not allowed as number suffix")
}
base := 10
if strings.HasPrefix(raw, "0x") {
raw = raw[2:]
base = 16
} else if strings.HasPrefix(raw, "0o") {
raw = raw[2:]
base = 8
} else if strings.HasPrefix(raw, "0b") {
raw = raw[2:]
base = 2
}
if isSignedInt(numberType) { if isSignedInt(numberType) {
return strconv.ParseInt(raw, 10, getBits(numberType)) num, err := strconv.ParseInt(raw, base, getBits(numberType))
if err != nil {
return nil, l.error("failed to parse literal: " + err.Error())
}
return num, nil
} }
if isUnsignedInt(numberType) { if isUnsignedInt(numberType) {
return strconv.ParseUint(raw, 10, getBits(numberType)) num, err := strconv.ParseUint(raw, base, getBits(numberType))
if err != nil {
return nil, l.error("failed to parse literal: " + err.Error())
}
return num, nil
} }
if isFloatingPoint(numberType) { if isFloatingPoint(numberType) {
return strconv.ParseFloat(raw, getBits(numberType)) if base != 10 {
return nil, l.error("non base 10 float literals are not supported")
} }
panic("Unhandled type (" + strconv.FormatUint(uint64(numberType), 10) + ") in parseNumber()") num, err := strconv.ParseFloat(raw, getBits(numberType))
if err != nil {
return nil, l.error("failed to parse literal: " + err.Error())
}
return num, nil
}
panic(fmt.Sprintf("Unhandled type %s in parseNumber()", numberType))
} }
func lexer(program string) ([]LexToken, error) { func lexer(program string) ([]LexToken, error) {

View File

@ -221,10 +221,10 @@ func (p *Parser) trySeparator(separators ...Separator) (*Separator, error) {
return &sep, nil return &sep, nil
} }
func (p *Parser) expectSeparator(separators ...Separator) (Separator, error) { func (p *Parser) expectSeparator(separators ...Separator) (*Separator, error) {
sep, err := p.trySeparator(separators...) sep, err := p.trySeparator(separators...)
if err != nil { if err != nil {
return InvalidValue, err return nil, err
} }
if sep == nil { if sep == nil {
@ -233,10 +233,10 @@ func (p *Parser) expectSeparator(separators ...Separator) (Separator, error) {
separatorNames = append(separatorNames, string(Separators[sep])) separatorNames = append(separatorNames, string(Separators[sep]))
} }
return InvalidValue, p.error("expected one of " + strings.Join(separatorNames, " ")) return nil, p.error("expected one of " + strings.Join(separatorNames, " "))
} }
return *sep, nil return sep, nil
} }
func (p *Parser) tryOperator(operators ...Operator) (*Operator, error) { func (p *Parser) tryOperator(operators ...Operator) (*Operator, error) {
@ -293,14 +293,35 @@ func (p *Parser) tryType() (*Type, error) {
if tok.Type == Type_Identifier { if tok.Type == Type_Identifier {
// TODO: array type // TODO: array type
var theType Type
index := slices.Index(PRIMITIVE_TYPE_NAMES, tok.Value.(string)) index := slices.Index(PRIMITIVE_TYPE_NAMES, tok.Value.(string))
if index != -1 { if index != -1 {
*p = pCopy theType = Type{Type: Type_Primitive, Value: PrimitiveType(index), Position: tok.Position}
return &Type{Type: Type_Primitive, Value: PrimitiveType(index), Position: tok.Position}, nil } else {
theType = Type{Type: Type_Named, Value: tok.Value, Position: tok.Position}
}
for {
sep, err := pCopy.trySeparator(Separator_OpenSquare)
if err != nil {
return nil, err
}
if sep == nil {
break
}
_, err = pCopy.expectSeparator(Separator_CloseSquare)
if err != nil {
return nil, err
}
theType = Type{Type: Type_Array, Value: ArrayType{ElementType: theType}, Position: theType.Position}
} }
*p = pCopy *p = pCopy
return &Type{Type: Type_Named, Value: tok.Value, Position: tok.Position}, nil return &theType, nil
} }
return nil, nil return nil, nil
@ -339,13 +360,13 @@ func (p *Parser) expectTypeOrTupleType() (*Type, error) {
types = append(types, *parsedType) types = append(types, *parsedType)
var sep Separator var sep *Separator
sep, err = p.expectSeparator(Separator_Comma, Separator_CloseParen) sep, err = p.expectSeparator(Separator_Comma, Separator_CloseParen)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if sep == Separator_CloseParen { if *sep == Separator_CloseParen {
break break
} }
} }

View File

@ -337,7 +337,7 @@ func (v *Validator) validateStatement(stmt *Statement, functionLocals *[]Local)
} }
if !isTypeExpandableTo(*ret.Value.ValueType, *v.currentFunction.ReturnType) { if !isTypeExpandableTo(*ret.Value.ValueType, *v.currentFunction.ReturnType) {
errors = append(errors, v.createError("expression type does not match function return type", ret.Value.Position)) errors = append(errors, v.createError(fmt.Sprintf("cannot return value of type %s from function returning %s", *ret.Value.ValueType, *v.currentFunction.ReturnType), ret.Value.Position))
} }
} else if v.currentFunction.ReturnType != nil { } else if v.currentFunction.ReturnType != nil {
errors = append(errors, v.createError("missing return value", stmt.Position)) errors = append(errors, v.createError("missing return value", stmt.Position))