quakeforge/ruamoko/scheme/builtins.r

357 lines
11 KiB
R
Raw Normal View History

#include "Void.h"
#include "Nil.h"
#include "Number.h"
#include "builtins.h"
#include "defs.h"
#include "string.h"
#include "Cons.h"
#include "Continuation.h"
#include "BaseContinuation.h"
#include "Boolean.h"
#include "Error.h"
BOOL num_args (SchemeObject *list, int num)
{
2011-02-14 13:39:43 +00:00
for (; [list isKindOfClass: [Cons class]]; list = [(Cons*) list cdr]) {
num--;
}
return num == 0;
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_display (SchemeObject *args, Machine *m)
{
if (!num_args(args, 1)) {
return [Error type: "display"
message: "expected 1 argument"
by: m];
}
2011-02-14 13:39:43 +00:00
print([[(Cons*) args car] printForm]);
return [Void voidConstant];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_newline (SchemeObject *args, Machine *m)
{
if (!num_args(args, 0)) {
return [Error type: "newline"
message: "expected no arguments"
by: m];
}
print("\n");
return [Void voidConstant];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_add (SchemeObject *args, Machine *m)
{
local int sum = 0;
2011-02-14 13:39:43 +00:00
local SchemeObject *cur;
2011-02-14 13:39:43 +00:00
for (cur = args; cur != [Nil nil]; cur = [(Cons*) cur cdr]) {
if (![[(Cons*) cur car] isKindOfClass: [Number class]]) {
return [Error type: "+"
message: sprintf("non-number argument: %s\n",
2011-02-14 13:39:43 +00:00
[[(Cons*) cur car] printForm])
by: m];
}
2011-02-14 13:39:43 +00:00
sum += [(Number*) [(Cons*) cur car] intValue];
}
return [Number newFromInt: sum];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_sub (SchemeObject *args, Machine *m)
{
local int diff = 0;
2011-02-14 13:39:43 +00:00
local SchemeObject *cur;
if (args == [Nil nil]) {
return [Error type: "-"
message: sprintf("expected at least 1 argument")
by: m];
}
2011-02-14 13:39:43 +00:00
cur = [(Cons*) args car];
if (![cur isKindOfClass: [Number class]]) {
return [Error type: "-"
message: sprintf("non-number argument: %s\n",
[cur printForm])
by: m];
}
2011-02-14 13:39:43 +00:00
diff = [(Number*) cur intValue];
2011-02-14 13:39:43 +00:00
if ([(Cons*) args cdr] == [Nil nil]) {
return [Number newFromInt: -diff];
}
2011-02-14 13:39:43 +00:00
for (cur = [(Cons*) args cdr]; cur != [Nil nil]; cur = [(Cons*) cur cdr]) {
if (![[(Cons*) cur car] isKindOfClass: [Number class]]) {
return [Error type: "-"
message: sprintf("non-number argument: %s\n",
2011-02-14 13:39:43 +00:00
[[(Cons*) cur car] printForm])
by: m];
}
2011-02-14 13:39:43 +00:00
diff -= [(Number*) [(Cons*) cur car] intValue];
}
return [Number newFromInt: diff];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_mult (SchemeObject *args, Machine *m)
{
local int prod = 1;
2011-02-14 13:39:43 +00:00
local SchemeObject *cur;
2011-02-14 13:39:43 +00:00
for (cur = args; cur != [Nil nil]; cur = [(Cons*) cur cdr]) {
if (![[(Cons*) cur car] isKindOfClass: [Number class]]) {
return [Error type: "*"
message: sprintf("non-number argument: %s\n",
2011-02-14 13:39:43 +00:00
[[(Cons*) cur car] printForm])
by: m];
}
2011-02-14 13:39:43 +00:00
prod *= [(Number*) [(Cons*) cur car] intValue];
}
return [Number newFromInt: prod];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_div (SchemeObject *args, Machine *m)
{
local int frac = 0;
2011-02-14 13:39:43 +00:00
local SchemeObject *cur;
if (args == [Nil nil]) {
return [Error type: "/"
message: sprintf("expected at least 1 argument")
by: m];
}
2011-02-14 13:39:43 +00:00
cur = [(Cons*) args car];
if (![cur isKindOfClass: [Number class]]) {
return [Error type: "/"
message: sprintf("non-number argument: %s\n",
[cur printForm])
by: m];
}
2011-02-14 13:39:43 +00:00
frac = [(Number*) cur intValue];
2011-02-14 13:39:43 +00:00
if ([(Cons*) args cdr] == [Nil nil]) {
return [Number newFromInt: 1/frac];
}
2011-02-14 13:39:43 +00:00
for (cur = [(Cons*) args cdr]; cur != [Nil nil]; cur = [(Cons*) cur cdr]) {
if (![[(Cons*) cur car] isKindOfClass: [Number class]]) {
return [Error type: "/"
message: sprintf("non-number argument: %s\n",
2011-02-14 13:39:43 +00:00
[[(Cons*) cur car] printForm])
by: m];
}
2011-02-14 13:39:43 +00:00
frac /= [(Number*) [(Cons*) cur car] intValue];
}
return [Number newFromInt: frac];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_cons (SchemeObject *args, Machine *m)
{
if (!num_args(args, 2)) {
return [Error type: "cons"
message: "expected 2 arguments"
by: m];
}
2011-02-14 13:39:43 +00:00
[(Cons*) args cdr: [(Cons*) [(Cons*) args cdr] car]];
return args;
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_null (SchemeObject *args, Machine *m)
{
if (!num_args(args, 1)) {
return [Error type: "null?"
message: "expected 1 argument"
by: m];
}
2011-02-14 13:39:43 +00:00
return [(Cons*) args car] == [Nil nil]
?
[Boolean trueConstant] :
[Boolean falseConstant];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_car (SchemeObject *args, Machine *m)
{
if (!num_args(args, 1)) {
return [Error type: "car"
message: "expected 1 argument"
by: m];
}
2011-02-14 13:39:43 +00:00
if (![[(Cons*) args car] isKindOfClass: [Cons class]]) {
return [Error type: "car"
message: sprintf("expected pair, got: %s",
2011-02-14 13:39:43 +00:00
[[(Cons*) args car] printForm])
by: m];
}
2011-02-14 13:39:43 +00:00
return [(Cons*) [(Cons*) args car] car];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_cdr (SchemeObject *args, Machine *m)
{
if (!num_args(args, 1)) {
return [Error type: "cdr"
message: "expected 1 argument"
by: m];
}
2011-02-14 13:39:43 +00:00
if (![[(Cons*) args car] isKindOfClass: [Cons class]]) {
return [Error type: "cdr"
message: sprintf("expected pair, got: %s",
2011-02-14 13:39:43 +00:00
[[(Cons*) args car] printForm])
by: m];
}
2011-02-14 13:39:43 +00:00
return [(Cons*) [(Cons*) args car] cdr];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_apply (SchemeObject *args, Machine *m)
{
2011-02-14 13:39:43 +00:00
local SchemeObject *cur, *prev;
if (args == [Nil nil]) {
return [Error type: "apply"
message: "expected at least 1 argument"
by: m];
2011-02-14 13:39:43 +00:00
} else if (![[(Cons*) args car] isKindOfClass: [Procedure class]]) {
return [Error type: "apply"
message:
sprintf("expected procedure as 1st argument, got: %s",
2011-02-14 13:39:43 +00:00
[[(Cons*) args car] printForm])
by: m];
}
2011-01-14 03:07:40 +00:00
prev = nil;
2011-02-14 13:39:43 +00:00
for (cur = args; [(Cons*) cur cdr] != [Nil nil]; cur = [(Cons*) cur cdr]) {
prev = cur;
}
if (prev) {
2011-02-14 13:39:43 +00:00
[(Cons*) prev cdr: [(Cons*) cur car]];
}
2011-02-14 13:39:43 +00:00
[m stack: [(Cons*) args cdr]];
[(Procedure*) [(Cons*) args car] invokeOnMachine: m];
2011-01-14 03:07:40 +00:00
return nil;
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_callcc (SchemeObject *args, Machine *m)
{
if (args == [Nil nil]) {
return [Error type: "call-with-current-continuation"
message: "expected at least 1 argument"
by: m];
2011-02-14 13:39:43 +00:00
} else if (![[(Cons*) args car] isKindOfClass: [Procedure class]]) {
return [Error type: "call-with-current-continuation"
message:
sprintf("expected procedure as 1st argument, got: %s",
2011-02-14 13:39:43 +00:00
[[(Cons*) args car] printForm])
by: m];
}
if ([m continuation]) {
[m stack: cons([m continuation], [Nil nil])];
} else {
[m stack: cons([BaseContinuation baseContinuation],
[Nil nil])];
}
2011-02-14 13:39:43 +00:00
[(Procedure*) [(Cons*) args car] invokeOnMachine: m];
2011-01-14 03:07:40 +00:00
return nil;
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_eq (SchemeObject *args, Machine *m)
{
if (!num_args(args, 2)) {
return [Error type: "eq?"
message: "expected 2 arguments"
by: m];
}
return
2011-02-14 13:39:43 +00:00
[(Cons*) args car] == [(Cons*) [(Cons*) args cdr] car] ?
[Boolean trueConstant] :
[Boolean falseConstant];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_numeq (SchemeObject *args, Machine *m)
{
2011-02-14 13:39:43 +00:00
local SchemeObject *num1, *num2;
if (!num_args(args, 2)) {
return [Error type: "="
message: "expected 2 arguments"
by: m];
}
2011-02-14 13:39:43 +00:00
num1 = [(Cons*) args car];
num2 = [(Cons*) [(Cons*) args cdr] car];
if (![num1 isKindOfClass: [Number class]]) {
return [Error type: "="
message: sprintf("expected number argument, got: %s",
[num1 printForm])
by: m];
} else if (![num2 isKindOfClass: [Number class]]) {
return [Error type: "="
message: sprintf("expected number argument, got: %s",
[num2 printForm])
by: m];
}
return
2011-02-14 13:39:43 +00:00
[(Number*) num1 intValue] == [(Number*) num2 intValue] ?
[Boolean trueConstant] :
[Boolean falseConstant];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_islist (SchemeObject *args, Machine *m)
{
if (!num_args(args, 1)) {
return [Error type: "list?"
message: "expected 1 argument"
by: m];
}
return
isList (args) ?
[Boolean trueConstant] :
[Boolean falseConstant];
}
2011-02-14 13:39:43 +00:00
SchemeObject *bi_ispair (SchemeObject *args, Machine *m)
{
if (!num_args(args, 1)) {
return [Error type: "pair?"
message: "expected 1 argument"
by: m];
}
return
2011-02-14 13:39:43 +00:00
[[(Cons*) args car] isKindOfClass: [Cons class]] ?
[Boolean trueConstant] :
[Boolean falseConstant];
}
#define builtin(name, func) [m addGlobal: symbol(#name) value: [Primitive newFromFunc: (func)]]
2011-02-14 13:39:43 +00:00
void builtin_addtomachine (Machine *m)
{
builtin(display, bi_display);
builtin(newline, bi_newline);
builtin(+, bi_add);
builtin(-, bi_sub);
builtin(*, bi_mult);
builtin(/, bi_div);
builtin(cons, bi_cons);
builtin(null?, bi_null);
builtin(car, bi_car);
builtin(cdr, bi_cdr);
builtin(apply, bi_apply);
builtin(call-with-current-continuation, bi_callcc);
builtin(eq?, bi_eq);
builtin(=, bi_numeq);
builtin(list?, bi_islist);
builtin(pair?, bi_ispair);
}