4 Commits

Author SHA1 Message Date
John Alanbrook
7b622d9788 initial attempt at adding IC 2025-06-23 17:20:39 -05:00
John Alanbrook
42087910ab remove proxy and many exotic methods 2025-06-23 15:32:05 -05:00
John Alanbrook
c581935fd8 add detail to cell.md 2025-06-23 10:21:33 -05:00
John Alanbrook
632b038561 remove last two master updates and remove proxy 2025-06-23 10:21:07 -05:00
8 changed files with 394 additions and 1288 deletions

View File

@@ -67,11 +67,11 @@ function Sun() {
var bodies = Array(Sun(), Jupiter(), Saturn(), Uranus(), Neptune()); var bodies = Array(Sun(), Jupiter(), Saturn(), Uranus(), Neptune());
function offsetMomentum() { function offsetMomentum() {
let px = 0; var px = 0;
let py = 0; var py = 0;
let pz = 0; var pz = 0;
var size = bodies.length; var size = bodies.length;
for (let i = 0; i < size; i++) { for (var i = 0; i < size; i++) {
var body = bodies[i]; var body = bodies[i];
var mass = body.mass; var mass = body.mass;
px += body.vx * mass; px += body.vx * mass;
@@ -88,12 +88,12 @@ function offsetMomentum() {
function advance(dt) { function advance(dt) {
var size = bodies.length; var size = bodies.length;
for (let i = 0; i < size; i++) { for (var i = 0; i < size; i++) {
var bodyi = bodies[i]; var bodyi = bodies[i];
let vxi = bodyi.vx; var vxi = bodyi.vx;
let vyi = bodyi.vy; var vyi = bodyi.vy;
let vzi = bodyi.vz; var vzi = bodyi.vz;
for (let j = i + 1; j < size; j++) { for (var j = i + 1; j < size; j++) {
var bodyj = bodies[j]; var bodyj = bodies[j];
var dx = bodyi.x - bodyj.x; var dx = bodyi.x - bodyj.x;
var dy = bodyi.y - bodyj.y; var dy = bodyi.y - bodyj.y;
@@ -117,7 +117,7 @@ function advance(dt) {
bodyi.vz = vzi; bodyi.vz = vzi;
} }
for (let i = 0; i < size; i++) { for (var i = 0; i < size; i++) {
var body = bodies[i]; var body = bodies[i];
body.x += dt * body.vx; body.x += dt * body.vx;
body.y += dt * body.vy; body.y += dt * body.vy;
@@ -126,16 +126,16 @@ function advance(dt) {
} }
function energy() { function energy() {
let e = 0; var e = 0;
var size = bodies.length; var size = bodies.length;
for (let i = 0; i < size; i++) { for (var i = 0; i < size; i++) {
var bodyi = bodies[i]; var bodyi = bodies[i];
e += 0.5 * bodyi.mass * ( bodyi.vx * bodyi.vx + e += 0.5 * bodyi.mass * ( bodyi.vx * bodyi.vx +
bodyi.vy * bodyi.vy + bodyi.vz * bodyi.vz ); bodyi.vy * bodyi.vy + bodyi.vz * bodyi.vz );
for (let j = i + 1; j < size; j++) { for (var j = i + 1; j < size; j++) {
var bodyj = bodies[j]; var bodyj = bodies[j];
var dx = bodyi.x - bodyj.x; var dx = bodyi.x - bodyj.x;
var dy = bodyi.y - bodyj.y; var dy = bodyi.y - bodyj.y;
@@ -154,7 +154,7 @@ offsetMomentum();
log.console(`n = ${n}`) log.console(`n = ${n}`)
log.console(energy().toFixed(9)) log.console(energy().toFixed(9))
for (let i = 0; i < n; i++) for (var i = 0; i < n; i++)
advance(0.01); advance(0.01);
log.console(energy().toFixed(9)) log.console(energy().toFixed(9))

View File

@@ -54,6 +54,12 @@ def libraries = [
getSize(encodedStr) { getSize(encodedStr) {
return encodedStr.length; return encodedStr.length;
} }
},
{
name: "jswota",
encode: jswota.encode,
decode: jswota.decode,
getSize(encoded) { return encoded.length }
} }
]; ];

40
cell.md
View File

@@ -6,6 +6,46 @@ CELLSCRIPT
Javascript to its core. Objects. What does the language need? It can be quite small, I think. The key is, ANYTHING that we want to be fast and JIT'd, must be present. So, record lookups. These are actually quicker in a jit'd language that have them as a feature. Most things should be libraries. Blobs need to be in the runtime. Javascript to its core. Objects. What does the language need? It can be quite small, I think. The key is, ANYTHING that we want to be fast and JIT'd, must be present. So, record lookups. These are actually quicker in a jit'd language that have them as a feature. Most things should be libraries. Blobs need to be in the runtime.
## Actors and Objects
Actors have a unique memory space and are made up of many objects. Objects are created in the Self style, but with a limitation: only one parent.
Actors only communicate with messages. Messages are a record of data consisting of a few base types: text, numbers, arrays, records, boolean values. There is no RPC, and it is not recommended to build it into your message passing protocol. Messages are very high level things: "do X", which the actor can then go and carry out.
Cell provides a fast way to condense an object for sending.
## How is it different from Javascript?
Cell condenses Javascript down into a few core ideas. There are three pillars which cell relies on:
1. The idea of actors as a method of communication between parts of a program.
2. The idea of objects as a way to organize and encapsulate data.
3. The idea of the capability model as security.
Javascript already supplied some of these things; Cell takes the core of Javascript and makes these ideas more explicit, and layers on the actor communication. It removes some goofy suckiness with javascript.
It acts as something like an operating system at the application level. It allows random code to be ran on your machine without worrying it will break something. This is built into the language.
It is completly dynamically typed. In comparison with C, in C, you can treat everything as everything: it is almost not typed at all. If you try to use a type as another type, no error is thrown; it might work, but it mightly silently not work. In Cell, data has a hard type, but if you use it "incorrectly", it will throw, and you can correct it. It's a live system.
Cell is linked very closely with C. It's best to think of cell as a layer for message passing on top of C. It is a way to describe how to translate C tasks from one section of the program to another - or to totally different computers (actors).
As such, cell's primary duty is marshalling data; so it has been designed for that to be as fast as possible. It has a syntax similar to C to make it easy to translate formulae from cell to C (or the other way, if desired).
Unlike many actor languages, Cell does not eschew assignment. You must have some assignment. However, when it comes to actor->actor communication, you do not assign. RPC is too direct: one actor should not care all that much what specific functions another actor has available. It should request it to do something, and get a result, or possibly not get a result. It doesn't care what the actor does as long as that gets done.
But within itself, it will assign; it must. Actors, or cells, are best thought of as computers or nodes within the internet. You request data from a URL by typing it into your browser; that computer you're attempting to reach may not even be on. It very likely has written some other data to disk whenever you contact it. But you're not doing the specific assigning. You just request data with HTTP commands.
## Objects and actors
Objects and actors are both similar ideas: they can hold data and respond to messages. Objects, local to an actor, can be thought of more like an RPC idea: they're invoked and return immediately. However, a failed RPC can crash an object; and in that case, the actor halts. It can be corrected.
## What does Cell bring you over C?
Programs which are built with C; they're built statically; they're built to not crash; they're built doing extremely low level things, like assignment.
The goal of cell is to thrust your C code into the parallel, actor realm. It lets your code crash and resume it; even rewriting the C code which is butressing your cell code and reloading it live.
There are two primary sorts of Cell modules you create from C code: data and IO. C code like
Where there were two similar things in javscript, one has been deleted and one kept. For example, there is only null now, no undefined. There are not four ways to test for equality; there is one.
The purpose of this is to be a great language for passing messages. So it should be fast at creating records first and foremost, and finding items on them. So it needs first class, jitt'd records. The purpose of this is to be a great language for passing messages. So it should be fast at creating records first and foremost, and finding items on them. So it needs first class, jitt'd records.
Finally, it needs to use less memory. Deleting a bunch of this stuff should make that simpler. Finally, it needs to use less memory. Deleting a bunch of this stuff should make that simpler.

View File

@@ -40,14 +40,14 @@ function console_rec(line, file, msg) {
var console_mod = cell.hidden.console var console_mod = cell.hidden.console
var logs = {} globalThis.log = {}
logs.console = function(msg) log.console = function(msg)
{ {
var caller = caller_data(2) var caller = caller_data(2)
console_mod.print(console_rec(caller.line, caller.file, msg)) console_mod.print(console_rec(caller.line, caller.file, msg))
} }
logs.error = function(msg = new Error()) log.error = function(msg = new Error())
{ {
var caller = caller_data(4) var caller = caller_data(4)
@@ -57,21 +57,11 @@ logs.error = function(msg = new Error())
console_mod.print(console_rec(caller.line,caller.file,msg)) console_mod.print(console_rec(caller.line,caller.file,msg))
} }
logs.system = function(msg) { log.system = function(msg) {
msg = "[SYSTEM] " + msg msg = "[SYSTEM] " + msg
log.console(msg) log.console(msg)
} }
function noop() {}
globalThis.log = new Proxy(logs, {
get(target,prop,receiver) {
if (target[prop])
return (...args) => target[prop](args.join(' '))
return noop
}
})
// Get hidden modules from cell.hidden before stripping it // Get hidden modules from cell.hidden before stripping it
var hidden = cell.hidden var hidden = cell.hidden
var actor_mod = hidden.actor var actor_mod = hidden.actor

View File

@@ -751,7 +751,6 @@ void script_startup(cell_rt *prt)
JS_AddIntrinsicRegExp(js); JS_AddIntrinsicRegExp(js);
JS_AddIntrinsicJSON(js); JS_AddIntrinsicJSON(js);
JS_AddIntrinsicMapSet(js); JS_AddIntrinsicMapSet(js);
JS_AddIntrinsicProxy(js);
JS_SetContextOpaque(js, prt); JS_SetContextOpaque(js, prt);
prt->context = js; prt->context = js;
@@ -870,79 +869,6 @@ int main(int argc, char **argv)
int profile_enabled = 0; int profile_enabled = 0;
int script_start = 1; int script_start = 1;
/* Check for --script flag - execute script directly without engine */
if (argc > 2 && strcmp(argv[1], "--script") == 0) {
/* Read and execute the script file */
FILE *f = fopen(argv[2], "rb");
if (!f) {
perror("fopen");
return 1;
}
fseek(f, 0, SEEK_END);
long size = ftell(f);
if (size < 0) {
perror("ftell");
fclose(f);
return 1;
}
char *script = malloc(size + 1);
if (!script) {
perror("malloc");
fclose(f);
return 1;
}
rewind(f);
if (fread(script, 1, size, f) != size) {
perror("fread");
free(script);
fclose(f);
return 1;
}
fclose(f);
script[size] = '\0';
/* Create minimal JS runtime */
JSRuntime *rt = JS_NewRuntime();
JSContext *js = JS_NewContextRaw(rt);
/* Add basic intrinsics */
JS_AddIntrinsicBaseObjects(js);
JS_AddIntrinsicEval(js);
JS_AddIntrinsicRegExp(js);
JS_AddIntrinsicJSON(js);
JS_AddIntrinsicMapSet(js);
JS_AddIntrinsicProxy(js);
cell_rt *prt = malloc(sizeof(*prt));
JS_SetContextOpaque(js, prt);
/* Load FFI functions */
ffi_load(js);
/* Execute the script */
JSValue result = JS_Eval(js, script, size, argv[2], 0);
free(script);
/* Check for exceptions */
if (JS_IsException(result)) {
JSValue exp = JS_GetException(js);
const char *str = JS_ToCString(js, exp);
if (str) {
fprintf(stderr, "Exception: %s\n", str);
JS_FreeCString(js, str);
}
JS_FreeValue(js, exp);
}
JS_FreeValue(js, result);
JS_FreeContext(js);
JS_FreeRuntime(rt);
return 0;
}
/* Check for --profile flag */ /* Check for --profile flag */
if (argc > 1 && strcmp(argv[1], "--profile") == 0) { if (argc > 1 && strcmp(argv[1], "--profile") == 0) {
profile_enabled = 1; script_start = 2; profile_enabled = 1; script_start = 2;

File diff suppressed because it is too large Load Diff

View File

@@ -455,12 +455,7 @@ typedef struct JSClassExoticMethods {
returned, the property descriptor 'desc' is filled if != NULL. */ returned, the property descriptor 'desc' is filled if != NULL. */
int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc, int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc,
JSValueConst obj, JSAtom prop); JSValueConst obj, JSAtom prop);
/* '*ptab' should hold the '*plen' property keys. Return 0 if OK,
-1 if exception. The 'is_enumerable' field is ignored.
*/
int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab,
uint32_t *plen,
JSValueConst obj);
/* return < 0 if exception, or TRUE/FALSE */ /* return < 0 if exception, or TRUE/FALSE */
int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop); int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop);
/* return < 0 if exception or TRUE/FALSE */ /* return < 0 if exception or TRUE/FALSE */
@@ -468,26 +463,6 @@ typedef struct JSClassExoticMethods {
JSAtom prop, JSValueConst val, JSAtom prop, JSValueConst val,
JSValueConst getter, JSValueConst setter, JSValueConst getter, JSValueConst setter,
int flags); int flags);
/* The following methods can be emulated with the previous ones,
so they are usually not needed */
/* return < 0 if exception or TRUE/FALSE */
int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom);
JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
JSValueConst receiver);
/* return < 0 if exception or TRUE/FALSE */
int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
JSValueConst value, JSValueConst receiver, int flags);
/* To get a consistent object behavior when get_prototype != NULL,
get_property, set_property and set_prototype must be != NULL
and the object must be created with a JS_NULL prototype. */
JSValue (*get_prototype)(JSContext *ctx, JSValueConst obj);
/* return < 0 if exception or TRUE/FALSE */
int (*set_prototype)(JSContext *ctx, JSValueConst obj, JSValueConst proto_val);
/* return < 0 if exception or TRUE/FALSE */
int (*is_extensible)(JSContext *ctx, JSValueConst obj);
/* return < 0 if exception or TRUE/FALSE */
int (*prevent_extensions)(JSContext *ctx, JSValueConst obj);
} JSClassExoticMethods; } JSClassExoticMethods;
typedef void JSClassFinalizer(JSRuntime *rt, JSValue val); typedef void JSClassFinalizer(JSRuntime *rt, JSValue val);
@@ -1031,6 +1006,10 @@ JSValue js_debugger_local_variables(JSContext *ctx, int stack_index);
JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc); JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc);
JSValue js_debugger_fn_info(JSContext *ctx, JSValue fn); JSValue js_debugger_fn_info(JSContext *ctx, JSValue fn);
/* Dump inline cache statistics for all functions */
void JS_DumpICStats(JSContext *ctx);
void JS_DumpOpcodeStats(JSContext *ctx);
#undef js_unlikely #undef js_unlikely
#undef js_force_inline #undef js_force_inline

View File

@@ -2,7 +2,6 @@
#define SPRITE_H #define SPRITE_H
#include "HandmadeMath.h" #include "HandmadeMath.h"
#include "render.h"
#include "cell.h" #include "cell.h"
struct sprite{ struct sprite{