Added string literals to generator
This commit is contained in:
		
							parent
							
								
									19b8825f5b
								
							
						
					
					
						commit
						e92377bc95
					
				| @ -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 { | ||||
|  | ||||
| @ -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)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user