Skip to content

Commit

Permalink
Merge pull request #18 from chibash/transpiler
Browse files Browse the repository at this point in the history
fixes issue #15
  • Loading branch information
maejima-fumika authored Oct 28, 2024
2 parents 5777704 + 092e865 commit d83c3c6
Show file tree
Hide file tree
Showing 18 changed files with 356 additions and 59 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/microcontroller_core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ jobs:
- uses: actions/checkout@v4

- name: Build c-runtime-test
run: gcc -DTEST64 c-runtime-test.c -o c-runtime-test
run: gcc -DTEST64 c-runtime-test.c -o c-runtime-test -lm

- name: Run c-runtime-test
run: ./c-runtime-test

- name: Build c-runtime-test2
run: gcc -DTEST64 c-runtime-test2.c -o c-runtime-test2
run: gcc -DTEST64 c-runtime-test2.c -o c-runtime-test2 -lm

- name: Run c-runtime-test2
run: ./c-runtime-test2

- name: Build float-test
run: gcc -DTEST64 float-test.c -o float-test
run: gcc -DTEST64 float-test.c -o float-test -lm

- name: Run float-test
run: ./float-test
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ To start using BlueScript, you'll need the following:
First, clone the BlueScript repository using Git:

```bash
git clone git@github.com:csg-tokyo/bluescript.git
git clone https://github.com/csg-tokyo/bluescript.git
```

### Build and Start the BlueScript Server
Expand Down
5 changes: 4 additions & 1 deletion microcontroller/core/include/c-runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ extern value_t CR_SECTION any_subtract(value_t a, value_t b);
extern value_t CR_SECTION any_multiply(value_t a, value_t b);
extern value_t CR_SECTION any_divide(value_t a, value_t b);
extern value_t CR_SECTION any_modulo(value_t a, value_t b);
extern value_t CR_SECTION any_power(value_t a, value_t b);
extern double CR_SECTION double_power(double a, double b);

extern bool CR_SECTION any_less(value_t a, value_t b);
extern bool CR_SECTION any_less_eq(value_t a, value_t b);
Expand Down Expand Up @@ -159,6 +161,7 @@ extern void CR_SECTION interrupt_handler_end();

extern void CR_SECTION gc_initialize();
extern class_object* CR_SECTION gc_get_class_of(value_t value);
extern bool gc_is_instance_of(const class_object* clazz, value_t obj);
extern void* CR_SECTION method_lookup(value_t obj, uint32_t index);

extern pointer_t CR_SECTION gc_allocate_object(const class_object* clazz);
Expand Down Expand Up @@ -208,8 +211,8 @@ extern value_t CR_SECTION gc_new_int_box(int32_t value);
extern value_t CR_SECTION gc_new_float_box(float value);

extern value_t CR_SECTION gc_new_string(char* str);
extern bool CR_SECTION gc_is_string_literal(value_t obj);
extern const char* CR_SECTION gc_string_literal_cstr(value_t obj);
extern bool CR_SECTION gc_is_string_object(value_t obj);

extern value_t CR_SECTION safe_value_to_intarray(value_t v);
extern value_t CR_SECTION gc_new_intarray(int32_t n, int32_t init_value);
Expand Down
54 changes: 49 additions & 5 deletions microcontroller/core/src/c-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
To run on a 64bit machine (for testing/debugging purpose only),
compile with -DTEST64. To include test code, compile with -DTEST.
So,
cc -DTEST -DTEST64 gc.c
cc -DTEST -DTEST64 gc.c -lm
will produce ./a.out that runs test code on a 64bit machine.
Typical usecase:
Expand Down Expand Up @@ -232,15 +232,15 @@ value_t safe_value_to_func(const char* signature, value_t func) {
}

value_t safe_value_to_string(value_t v) {
if (!gc_is_string_literal(v))
if (!gc_is_string_object(v))
runtime_type_error("value_to_string");

return v;
}

value_t safe_value_to_object(value_t v) {
// note: String is not a subtype of Object
if (!is_ptr_value(v) || gc_is_string_literal(v))
if (!is_ptr_value(v) || gc_is_string_object(v))
runtime_type_error("value_to_object");

return v;
Expand Down Expand Up @@ -287,6 +287,36 @@ value_t any_modulo(value_t a, value_t b) {
return runtime_type_error("bad operand for %%");
}

value_t any_power(value_t a, value_t b) {
double x, y;
int int_type = 1;
if (is_int_value(a))
x = value_to_int(a);
else if (is_float_value(a)) {
x = value_to_float(a);
int_type = 0;
}
else
return runtime_type_error("bad operand for **");

if (is_int_value(b))
y = value_to_int(b);
else if (is_float_value(b)) {
y = value_to_float(b);
int_type = 0;
}
else
return runtime_type_error("bad operand for **");

double z = pow(x, y);
if (int_type)
return int_to_value((int32_t)z);
else
return float_to_value((float)z);
}

double double_power(double a, double b) { return pow(a, b); }

#define ANY_CMP_FUNC(name, op) \
bool any_##name(value_t a, value_t b) {\
if (is_int_value(a)) {\
Expand Down Expand Up @@ -432,6 +462,15 @@ class_object* gc_get_class_of(value_t value) {
return NULL;
}

bool gc_is_instance_of(const class_object* clazz, value_t obj) {
const class_object* obj_class = gc_get_class_of(obj);
do {
if (obj_class == clazz)
return true;
} while (obj_class != NULL && (obj_class = obj_class->superclass));
return false;
}

void* method_lookup(value_t obj, uint32_t index) {
return get_objects_class(value_to_ptr(obj))->vtbl[index];
}
Expand Down Expand Up @@ -668,16 +707,21 @@ value_t gc_new_string(char* str) {
}

// true if this is a string literal object.
bool gc_is_string_literal(value_t obj) {
static bool gc_is_string_literal(value_t obj) {
return gc_get_class_of(obj) == &string_literal.clazz;
}

// returns a pointer to a char array in the C language.
// this function is only used in test-code-generator.ts.
const char* gc_string_literal_cstr(value_t obj) {
pointer_t str = value_to_ptr(obj);
return (const char*)raw_value_to_ptr(str->body[0]);
}

bool gc_is_string_object(value_t obj) {
return gc_is_string_literal(obj);
}

// An int32_t array

static CLASS_OBJECT(intarray_object, 1) = {
Expand Down Expand Up @@ -1301,7 +1345,7 @@ static void scan_and_mark_objects(uint32_t mark) {
while (start < end) {
pointer_t obj = (pointer_t)&heap_memory[start];
class_object* clazz = get_objects_class(obj);
int32_t j = class_has_pointers(clazz);
// int32_t j = class_has_pointers(clazz);
uint32_t size = object_size(obj, clazz);
if (IS_GRAY(obj)) {
gc_stack[0] = obj;
Expand Down
2 changes: 1 addition & 1 deletion microcontroller/core/test/c-runtime-test.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Test code
// To cmpile,
// cc -DTEST64 c-runtime-test.c
// cc -DTEST64 c-runtime-test.c -lm

#include <string.h>
#include "../src/c-runtime.c"
Expand Down
2 changes: 1 addition & 1 deletion microcontroller/core/test/c-runtime-test2.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Test code for c-runtime.c
// To compile,
// cc -DTEST64 c-runtime-test2.c
// cc -DTEST64 c-runtime-test2.c -lm

#include <stdio.h>
#include "../src/c-runtime.c"
Expand Down
2 changes: 1 addition & 1 deletion microcontroller/core/test/float-test.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Test code for value_to_float and float_to_value functions in c-runtime.c
// To compile,
// cc -DTEST64 float-test.c
// cc -DTEST64 float-test.c -lm

#include <stdio.h>
#include <stdlib.h>
Expand Down
2 changes: 1 addition & 1 deletion modules/esp32/c/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void fbody_print(value_t self, value_t _value) {
sprintf(message, "%f\n", value_to_float(_value));
else if (_value == VALUE_NULL)
sprintf(message, "null\n");
else if (gc_is_string_literal(_value))
else if (gc_is_string_object(_value))
sprintf(message, "%s\n", gc_string_literal_cstr(_value));
else
sprintf(message, "??\n");
Expand Down
17 changes: 15 additions & 2 deletions server/src/transpiler/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class InstanceType extends ObjectType {
private numOfUnboxed: number | undefined = undefined
private numOfMethods: number
private superClass: ObjectType
private subClasses: InstanceType[] = []
private className: string
private blueScriptName: string

Expand All @@ -28,15 +29,17 @@ export class InstanceType extends ObjectType {

// returns a globally-unique class name. It may be different from the
// original name given in the source code.
name() { return this.className }
override name() { return this.className }

// the name given in the source code.
override sourceName() { return this.blueScriptName }

superType(): ObjectType | null { return this.superClass }
override superType(): ObjectType | null { return this.superClass }

superclass(): ObjectType { return this.superClass }

subclasses(): InstanceType[] { return this.subClasses }

// false if this class extends another class that is not Object class.
extendsObject() { return !(this.superClass instanceof InstanceType) }

Expand Down Expand Up @@ -210,14 +213,19 @@ export class InstanceType extends ObjectType {
export class ClassTable {
private names
private numOfNames
private rootClasses: InstanceType[]

constructor() {
this.names = new Map<string, number>()
this.numOfNames = 0
this.rootClasses = []
const builtinMethods: string[] = [ArrayType.lengthMethod]
builtinMethods.forEach(name => { this.names.set(name, this.numOfNames++) })
}

// returns all the classes that do not inherit from another class.
roots() { return this.rootClasses }

// clazz must be added after all properties and methods are
// added to it.
addClass(name: string, clazz: InstanceType) {
Expand All @@ -228,6 +236,11 @@ export class ClassTable {

clazz.forEachName(f)
clazz.forEachMethodName(f)
const sup = clazz.superclass()
if (sup instanceof InstanceType)
sup.subclasses().push(clazz)
else
this.rootClasses.push(clazz)
}

encodeName(name: string) {
Expand Down
19 changes: 18 additions & 1 deletion server/src/transpiler/code-generator/c-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ export function arithmeticOpForAny(op: string) {
return 'any_divide'
case '%':
return 'any_modulo'
case '**':
return 'any_power'
case '+=':
return 'any_add_assign'
case '-=':
Expand All @@ -228,6 +230,15 @@ export function arithmeticOpForAny(op: string) {
}
}

export function power(type: StaticType | undefined) {
if (type === Float)
return '(float)double_power('
else if (type === Integer)
return '(int32_t)double_power('
else
throw new Error('bad operand types for **')
}

export function updateOpForAny(prefix: boolean, op: string) {
if (prefix)
if (op === '++')
Expand Down Expand Up @@ -380,7 +391,9 @@ export function getArrayLengthIndex(t: StaticType) {
}

export const runtimeTypeArray = 'array_object'
export const arrayMaker = 'gc_new_string'

export const stringMaker = 'gc_new_string'
export const isStringType = 'gc_is_string_object('

export const functionMaker = 'gc_new_function'
export const functionPtr = 'fptr'
Expand Down Expand Up @@ -478,3 +491,7 @@ export function makeInstance(clazz: InstanceType) {
export function methodLookup(method: [StaticType, number, InstanceType], func: string) {
return `((${funcTypeToCType(method[0])})method_lookup(${func}, ${method[1]}))`
}

export function isInstanceOf(t: InstanceType) {
return `gc_is_instance_of(&${classObjectNameInC(t.name())}, `
}
Loading

0 comments on commit d83c3c6

Please sign in to comment.