Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lang/src/transpiler/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ export class InstanceType extends ObjectType {
const k = this.superClass.unboxedProperties()
if (k === undefined || k !== size) {
this.numOfUnboxed = k
return
return false // cannot move properties
}

index = size
Expand All @@ -270,6 +270,8 @@ export class InstanceType extends ObjectType {
if (!isPrimitiveType(value[0]))
value[1] = index++
}

return true
}

findConstructor() { return this.constructorFunction }
Expand Down
59 changes: 35 additions & 24 deletions lang/src/transpiler/code-generator/c-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

import * as AST from '@babel/types'
import { ErrorLog } from '../utils'
import { Integer, Float, BooleanT, StringT, Void, Null, Any,
import { Integer, Int32, Float, BooleanT, StringT, Void, Null, Any,
ObjectType, objectType, FunctionType,
StaticType, isPrimitiveType, typeToString, ArrayType, sameType, encodeType, isSubtype,
StaticType, isPrimitiveType, isIntegerLike, typeToString, ArrayType, sameType, encodeType, isSubtype,
ByteArrayClass, UnionType, EnumType,
VectorClass} from '../types'
FixedArrayClass,
isIntegerType} from '../types'
import { InstanceType, ClassTable, StaticPropertyInfo } from '../classes'
import { VariableEnv } from './variables'

Expand Down Expand Up @@ -51,6 +52,7 @@ function typeToCType2(type: StaticType): string {
else
switch (type) {
case Integer:
case Int32:
return 'int32_t'
case Float:
return 'float'
Expand Down Expand Up @@ -82,7 +84,7 @@ export function typeConversion(from: StaticType | undefined, to: StaticType | un
return '('

if (sameType(from, to))
if (from === Integer || from instanceof EnumType)
if (from === Integer || from === Int32 || from instanceof EnumType)
return '(int32_t)('
else if (from === Float)
return '(float)('
Expand All @@ -100,23 +102,24 @@ export function typeConversion(from: StaticType | undefined, to: StaticType | un

switch (to) {
case Integer:
case Int32:
if (from === Float)
return '(int32_t)('
else if (from === BooleanT || from instanceof EnumType)
else if (isIntegerType(from) || from === BooleanT || from instanceof EnumType)
return '('
else if (from === Any || from instanceof UnionType)
return 'safe_value_to_int('
else
break
case Float:
if (from === Integer || from === BooleanT || from instanceof EnumType)
if (from === Integer || from === Int32 || from === BooleanT || from instanceof EnumType)
return '(float)('
else if (from === Any || from instanceof UnionType)
return 'safe_value_to_float('
else
break
case BooleanT:
if (from === Integer || from instanceof EnumType)
if (from === Integer || from === Int32 || from instanceof EnumType)
return '('
else if (from === Float)
return '(int32_t)('
Expand All @@ -133,6 +136,8 @@ export function typeConversion(from: StaticType | undefined, to: StaticType | un
switch (from) {
case Integer:
return 'int_to_value('
case Int32:
throw typeConversionError(from, to, node)
case Float:
return 'float_to_value('
case BooleanT:
Expand All @@ -155,7 +160,7 @@ export function typeConversion(from: StaticType | undefined, to: StaticType | un
if (to === objectType)
return 'safe_value_to_object(false, '
else if (to instanceof ArrayType) {
if (to.elementType === Integer || to.elementType instanceof EnumType)
if (isIntegerLike(to.elementType))
return 'safe_value_to_intarray(false, '
else if (to.elementType === Float)
return 'safe_value_to_floatarray(false, '
Expand Down Expand Up @@ -196,7 +201,7 @@ function typeConversionToUnion(from: StaticType, to: UnionType, env: VariableEnv
if (objType === objectType)
return 'safe_value_to_object(true, '
else if (objType instanceof ArrayType) {
if (objType.elementType === Integer || objType.elementType instanceof EnumType)
if (isIntegerLike(objType.elementType))
return 'safe_value_to_intarray(true, '
else if (objType.elementType === Float)
return 'safe_value_to_floatarray(true, '
Expand Down Expand Up @@ -281,7 +286,7 @@ export const anyAddMember = 'any_add_member'
export function power(type: StaticType | undefined) {
if (type === Float)
return '(float)double_power('
else if (type === Integer)
else if (type === Integer || type === Int32)
return '(int32_t)double_power('
else
throw new Error('bad operand types for **')
Expand Down Expand Up @@ -380,37 +385,37 @@ export function makeBoxedValue(type: StaticType, value?: string) {
export function arrayElementGetter(t: StaticType | undefined, arrayType: StaticType | undefined, node: AST.Node) {
if (arrayType instanceof InstanceType && arrayType.name() === ByteArrayClass)
return '(*gc_bytearray_get('
else if (arrayType instanceof InstanceType && arrayType.name() === VectorClass)
return '(gc_vector_get('
else if (arrayType instanceof InstanceType && arrayType.name() === FixedArrayClass)
return '(gc_fixedarray_get('
else if (arrayType === Any)
return '(gc_safe_array_get('
else if (t === Integer || t instanceof EnumType)
else if (t === Integer || t === Int32 || t instanceof EnumType)
return '(*gc_intarray_get('
else if (t === Float)
return '(*gc_floatarray_get('
else if (t === BooleanT)
return '(*gc_bytearray_get('
else
return `(*gc_array_get(`
return `(gc_safe_array_get(`
}

export function arrayElementSetter(arrayType: StaticType | undefined) {
if (arrayType === undefined)
throw new Error('unknown array type')
else if (arrayType === Any)
return 'gc_safe_array_set('
else if (arrayType instanceof InstanceType && arrayType.name() === VectorClass)
return 'gc_vector_set('
else if (arrayType instanceof InstanceType && arrayType.name() === FixedArrayClass)
return 'gc_fixedarray_set('
else
return `gc_array_set(`
return `gc_safe_array_set(`
}

export const accumulateInUnknownArray = 'gc_safe_array_acc'

// makes an array object from elements
export function arrayFromElements(arrayType: ArrayType, env: VariableEnv) {
const t = arrayType.elementType
if (t === Integer || t instanceof EnumType)
if (isIntegerLike(t))
return 'gc_make_intarray('
else if (t === Float)
return 'gc_make_floatarray('
Expand All @@ -424,7 +429,7 @@ export function arrayFromElements(arrayType: ArrayType, env: VariableEnv) {

export function arrayFromSize(arrayType: ArrayType, env: VariableEnv) {
const t = arrayType.elementType
if (t === Integer || t instanceof EnumType)
if (isIntegerLike(t))
return 'gc_new_intarray('
else if (t === Float)
return 'gc_new_floatarray('
Expand All @@ -438,7 +443,7 @@ export function arrayFromSize(arrayType: ArrayType, env: VariableEnv) {

export function arrayFromArray(arrayType: ArrayType, env: VariableEnv) {
const t = arrayType.elementType
if (t === Integer || t instanceof EnumType)
if (isIntegerLike(t))
return 'gc_copy_intarray('
else if (t === Float)
return 'gc_copy_floatarray('
Expand All @@ -453,7 +458,9 @@ export function arrayFromArray(arrayType: ArrayType, env: VariableEnv) {
export const prefixOfarrayTypeNameInC = 'array_type'

export function actualElementType(t: StaticType) {
if (t === Integer || t instanceof EnumType)
if (t === Int32)
return Int32
else if (t === Integer || t instanceof EnumType)
return Integer
else if (t === Float)
return Float
Expand Down Expand Up @@ -595,16 +602,20 @@ export function makeInstance(clazz: InstanceType, func: () => string) {
const name = clazz.name()
if (name === ByteArrayClass)
return 'gc_new_bytearray(false'
else if (name === VectorClass)
return 'gc_new_vector('
else if (name === FixedArrayClass)
return 'gc_new_fixedarray('
else
return `${constructorNameInC(name)}(${func()}gc_new_object(&${classObjectNameInC(name)})`
}

export function methodLookup(method: [StaticType, number, InstanceType?], func: string) {
export function methodLookup(method: [StaticType, number, (InstanceType | ArrayType)?], func: string) {
return `((${funcTypeToCType(method[0])})gc_method_lookup(${func}, ${method[1]}))`
}

export function isArrayObject(f: string) {
return `safe_anyarray_to_anyarrayobj(${f})`
}

export const dynamicMethodCall = 'gc_dynamic_method_call'

export function isInstanceOf(t: InstanceType) {
Expand Down
39 changes: 30 additions & 9 deletions lang/src/transpiler/code-generator/code-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import * as AST from '@babel/types'
import { runBabelParser, ErrorLog, CodeWriter } from '../utils'
import { Integer, BooleanT, Void, Any, ObjectType, FunctionType,
import { Integer, Int32, BooleanT, Void, Any, ObjectType, FunctionType,
StaticType, ByteArrayClass, isPrimitiveType, encodeType, sameType, typeToString, ArrayType, objectType,
StringT, UnionType, VectorClass, StringType,
StringT, UnionType, FixedArrayClass, StringType,
EnumType} from '../types'
import * as visitor from '../visitor'
import { getCoercionFlag, getStaticType } from '../names'
Expand Down Expand Up @@ -228,9 +228,9 @@ export class CodeGenerator extends visitor.NodeVisitor<VariableEnv> {
})

if (frees.length > 0) {
// all the arguments to gc_make_vector must be reachable
// all the arguments to gc_make_fixedarray must be reachable
// from the garbage-collection root.
obj = `gc_make_vector(${frees.length}${args})`
obj = `gc_make_fixedarray(${frees.length}${args})`
}
}

Expand Down Expand Up @@ -1089,7 +1089,15 @@ export class CodeGenerator extends visitor.NodeVisitor<VariableEnv> {

const left_type = this.needsCoercion(left)
const right_type = this.needsCoercion(right)
if ((left_type === BooleanT || right_type === BooleanT)
if (left_type === Int32 && right_type === Any || left_type === Any && right_type === Int32) {
this.result.write(`${cr.typeConversion(left_type, Int32, env, left)}`)
this.visit(left, env)
this.result.write(`) ${op2} `)
this.result.write(`${cr.typeConversion(right_type, Int32, env, right)}`)
this.visit(right, env)
this.result.write(')')
}
else if ((left_type === BooleanT || right_type === BooleanT)
// if either left or right operand is boolean, the other is boolean
|| (left_type === StringT || right_type === StringT)
|| (left_type === Any || right_type === Any)
Expand All @@ -1108,7 +1116,15 @@ export class CodeGenerator extends visitor.NodeVisitor<VariableEnv> {
private basicBinaryExpression(op: string, node: AST.BinaryExpression, left: AST.Node, right: AST.Node, env: VariableEnv): void {
const left_type = this.needsCoercion(left)
const right_type = this.needsCoercion(right)
if (left_type === Any || right_type === Any || left_type === StringT || right_type === StringT) {
if (left_type === Int32 && right_type === Any || left_type === Any && right_type === Int32) {
this.result.write(`${cr.typeConversion(left_type, Int32, env, left)}`)
this.visit(left, env)
this.result.write(`) ${op} `)
this.result.write(`${cr.typeConversion(right_type, Int32, env, right)}`)
this.visit(right, env)
this.result.write(')')
}
else if (left_type === Any || right_type === Any || left_type === StringT || right_type === StringT) {
this.result.write(`${cr.arithmeticOpForAny(op)}(${cr.typeConversion(left_type, Any, env, left)}`)
this.visit(left, env)
this.result.write(`), ${cr.typeConversion(right_type, Any, env, right)}`)
Expand Down Expand Up @@ -1486,7 +1502,12 @@ export class CodeGenerator extends visitor.NodeVisitor<VariableEnv> {
}
else {
// a method call on a typed object
this.result.write(`, ${cr.methodLookup(method[0], func)}(${func}`)
let funcExpr = func
const minfo = method[0]
if (minfo[2] instanceof ArrayType && minfo[2].elementType === Any)
funcExpr = cr.isArrayObject(func)

this.result.write(`, ${cr.methodLookup(method[0], funcExpr)}(${func}`)
}
}
else {
Expand Down Expand Up @@ -1693,7 +1714,7 @@ export class CodeGenerator extends visitor.NodeVisitor<VariableEnv> {
this.visit(node.object, env)
this.result.write(`, ${cr.getArrayLengthIndex(BooleanT)})`)
}
else if (propertyName === ArrayType.lengthProperty && objType.name() === VectorClass) {
else if (propertyName === ArrayType.lengthProperty && objType.name() === FixedArrayClass) {
this.result.write(cr.getObjectPrimitiveProperty(Integer))
this.visit(node.object, env)
this.result.write(`, ${cr.getArrayLengthIndex(Any)})`)
Expand Down Expand Up @@ -1740,7 +1761,7 @@ export class CodeGenerator extends visitor.NodeVisitor<VariableEnv> {

// This returns method_info, method_name, or undefined.
visitIfMethodExpr(node: AST.MemberExpression, env: VariableEnv):
[ method: [method_type: StaticType, method_table_index: number, declaring_class?: InstanceType],
[ method: [method_type: StaticType, method_table_index: number, declaring_class?: InstanceType | ArrayType],
is_call_on_super_or_not: boolean] | string | undefined {
if (node.computed)
return undefined
Expand Down
Loading
Loading