Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes issue #15 #18

Merged
merged 12 commits into from
Oct 28, 2024
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