Added string literals to generator

This commit is contained in:
Sasha Koshka 2023-11-29 00:01:35 -05:00
parent 19b8825f5b
commit e92377bc95
3 changed files with 85 additions and 12 deletions

View File

@ -95,8 +95,6 @@ func (this *Tree) analyzeLiteralString (
"assigning to %v",
into)
}
// TODO figure out if it can fit
case *entity.TypeArray:
element := ReduceToBase(base.Element)
if element, ok := element.(*entity.TypeInt); !ok {

View File

@ -74,7 +74,7 @@ func (this *Compiler) Compile (inputs []string) error {
return err
default:
return errors.New(fmt.Sprintf (
"unknown output type %", extension))
"unknown output type %s", extension))
}
}

View File

@ -88,24 +88,99 @@ func (this *generator) generateLiteralArrayLoc (literal *entity.LiteralArray) (l
}
func (this *generator) generateLiteralStringLoc (literal *entity.LiteralString) (llvm.Value, error) {
ty := analyzer.ReduceToBase(literal.Type())
base := analyzer.ReduceToBase(literal.Type())
makeData := func (elementType entity.Type) (llvm.Value, int64, error) {
makeData := func (anyElementType entity.Type) (llvm.Value, int64, error) {
elementType, ok := anyElementType.(*entity.TypeInt)
if !ok {
return nil, 0, errors.New(fmt.Sprintln("string can't be used as ", base))
}
switch {
case elementType.Width >= 32:
length := len(literal.ValueUTF32)
irArrayType, err := this.generateType(&entity.TypeArray {
Element: elementType,
Length: length,
})
if err != nil { return nil, 0, err }
array := this.blockManager.newAllocaFront(irArrayType)
for index, element := range literal.ValueUTF32 {
elementPointer := this.blockManager.NewGetElementPtr (
irArrayType, array,
llvm.NewConstInt(llvm.I32, 0),
llvm.NewConstInt(llvm.I32, int64(index)))
this.blockManager.NewStore (
llvm.NewConstInt(llvm.I32, int64(element)),
elementPointer)
}
return array, int64(length), nil
case elementType.Width >= 16:
length := len(literal.ValueUTF16)
irArrayType, err := this.generateType(&entity.TypeArray {
Element: elementType,
Length: length,
})
if err != nil { return nil, 0, err }
array := this.blockManager.newAllocaFront(irArrayType)
for index, element := range literal.ValueUTF16 {
elementPointer := this.blockManager.NewGetElementPtr (
irArrayType, array,
llvm.NewConstInt(llvm.I32, 0),
llvm.NewConstInt(llvm.I32, int64(index)))
this.blockManager.NewStore (
llvm.NewConstInt(llvm.I16, int64(element)),
elementPointer)
}
return array, int64(length), nil
default:
length := len(literal.ValueUTF8)
irArrayType, err := this.generateType(&entity.TypeArray {
Element: elementType,
Length: length,
})
if err != nil { return nil, 0, err }
array := this.blockManager.newAllocaFront(irArrayType)
for index, element := range literal.ValueUTF8 {
elementPointer := this.blockManager.NewGetElementPtr (
irArrayType, array,
llvm.NewConstInt(llvm.I32, 0),
llvm.NewConstInt(llvm.I32, int64(index)))
this.blockManager.NewStore (
llvm.NewConstInt(llvm.I8, int64(element)),
elementPointer)
}
return array, int64(length), nil
}
}
switch ty := ty.(type) {
switch base := base.(type) {
case *entity.TypeInt:
// TODO
var value llvm.Value
irType, err := this.generateType(base)
if err != nil { return nil, err }
switch {
case base.Width >= 32:
value = llvm.NewConstInt(llvm.I32, int64(literal.ValueUTF32[0]))
case base.Width >= 16:
value = llvm.NewConstInt(llvm.I16, int64(literal.ValueUTF16[0]))
default:
value = llvm.NewConstInt(llvm.I8, int64(literal.ValueUTF8[0]))
}
char := this.blockManager.newAllocaFront(irType)
this.blockManager.NewStore(value, char)
return char, nil
case *entity.TypeArray:
value, _, err := makeData(ty.Element)
value, _, err := makeData(base.Element)
return value, err
case *entity.TypeSlice:
array, length, err := makeData(ty.Element)
array, length, err := makeData(base.Element)
if err != nil { return nil, err }
irType, err := this.generateTypeSlice(ty)
irType, err := this.generateType(base)
if err != nil { return nil, err }
slice := this.blockManager.newAllocaFront(irType)
data := this.blockManager.NewGetElementPtr (
@ -132,12 +207,12 @@ func (this *generator) generateLiteralStringLoc (literal *entity.LiteralString)
return slice, nil
case *entity.TypePointer:
array, _, err := makeData(ty.Referenced)
array, _, err := makeData(base.Referenced)
if err != nil { return nil, err }
return this.valueToLocation(array), nil
default:
return nil, errors.New(fmt.Sprintln("string can't be used as ", ty))
return nil, errors.New(fmt.Sprintln("string can't be used as ", base))
}
}