浏览代码

handle comparisons between pointers and arrays, handle taking address of array

master
Ian Piumarta 5 个月前
父节点
当前提交
49c896a266
共有 5 个文件被更改,包括 84 次插入27 次删除
  1. +2
    -2
      demofiles/pointer-compare.c
  2. +4
    -4
      demofiles/pointer-out-of-bounds.c
  3. +4
    -1
      include/stdlib.h
  4. +61
    -19
      main.leg
  5. +13
    -1
      test.txt

+ 2
- 2
demofiles/pointer-compare.c 查看文件

@ -9,7 +9,7 @@ int main() {
int *p = array + 2;
int *q = array + 4;
int *r = brray + 4;
if (p > q) abort();
if (p > r) abort(); // illegal comparison
if (p > q) abort(); printf("compare OK\n");
if (p < r) abort(); printf("compare OK\n"); // illegal comparison
return 0;
}

+ 4
- 4
demofiles/pointer-out-of-bounds.c 查看文件

@ -3,8 +3,8 @@
#include <stdio.h>
int main() {
int array[5] = {0, 1, 2, 3, 4};
int *ptr = &array[5];
*ptr = 42;
return 0;
int array[5] = {0, 1, 2, 3, 4};
int *ptr = &array[5];
*ptr = 42;
return 0;
}

+ 4
- 1
include/stdlib.h 查看文件

@ -1,2 +1,5 @@
extern void *malloc(long size);
extern void free(void *pointer);
extern void free(void *pointer);
extern void exit(int status);
extern void abort(void);

+ 61
- 19
main.leg 查看文件

@ -1,6 +1,6 @@
# main.leg -- C parser + interpreter
#
# Last edited: 2025-01-29 16:00:13 by piumarta on xubuntu
# Last edited: 2025-01-29 18:13:39 by piumarta on zora
%{
;
@ -98,8 +98,8 @@ char *binaryName(int op) {
#undef _
#define _do_primitives(_) \
_(printf) _(assert) _(malloc) _(free)
#define _do_primitives(_) \
_(printf) _(assert) _(malloc) _(free) _(exit) _(abort)
#define _(X) oop s_##X = 0;
_do_primitives(_)
@ -2310,6 +2310,22 @@ oop prim_free(int argc, oop *argv, oop env) // array
return nil;
}
oop prim_exit(int argc, oop *argv, oop env) // array
{
if (argc != 1) fatal("exit: wrong number of arguments");
oop arg = argv[0];
if (!is(Integer,arg)) fatal("exit: argument is not an integer");
exit(_integerValue(arg));
return nil;
}
oop prim_abort(int argc, oop *argv, oop env) // array
{
if (argc != 0) fatal("abort: wrong number of arguments");
abort();
return nil;
}
oop typeCheck(oop exp, oop fntype)
{
switch (getType(exp)) {
@ -2903,18 +2919,24 @@ int equal(oop a, oop b)
}
fatal("cannot compare %ss", getTypeName(a));
}
else {
if (is(Pointer, a) && is(Integer, b)) {
oop base = get(a, Pointer,base);
if (is(Integer, base)) {
oop type = get(a, Pointer,type);
int offset = get(a, Pointer,offset);
int scale = typeSize(get(type, Tpointer,target));
return _integerValue(base) + offset * scale == _integerValue(b);
}
return 0;
}
if (is(Pointer, a) && is(Integer, b)) {
oop base = get(a, Pointer,base);
if (is(Integer, base)) {
oop type = get(a, Pointer,type);
int offset = get(a, Pointer,offset);
int scale = typeSize(get(type, Tpointer,target));
return _integerValue(base) + offset * scale == _integerValue(b);
}
return 0;
}
if (is(Array, a) && is(Pointer, b)) {
oop ba = get(a, Array,base), bb = get(b, Pointer,base);
return (ba == bb) && (get(b, Pointer,offset) == 0);
}
if (is(Pointer, a) && is(Array, b)) return equal(b, a);
fatal("cannot compare %s with %s", getTypeName(a), getTypeName(b));
return 0;
}
@ -3015,13 +3037,33 @@ oop eval(oop exp, oop env)
rhs = Scope_lookup(rhs);
if (!rhs) assert(!"this cannot happen");
switch (getType(rhs)) {
case Variable:
case Variable: {
oop type = get(rhs, Variable,type);
if (is(Tarray,type)) return get(rhs, Variable,value);
return newPointer(newTpointer(get(rhs, Variable,type)), rhs, 0);
}
default:
break;
}
break;
}
case Index: {
oop ondex = eval(get(rhs, Index,rhs), nil);
if (!is(Integer, ondex)) fatal("array index is not 'int'");
int index = _integerValue(ondex);
oop lhs = eval(get(rhs, Index,lhs), nil);
switch (getType(lhs)) {
case Array: {
oop type = get(lhs, Array,type);
oop base = get(lhs, Array,base); // xxx check index against size
return newPointer(newTpointer(get(type, Tarray,target)), base, index);
}
default: break;
}
println(lhs);
fatal("cannot take address");
break;
}
default:
break;
}
@ -3144,10 +3186,10 @@ oop eval(oop exp, oop env)
case SUB: return IBINOP(lhs, - , rhs);
case SHL: return IBINOP(lhs, <<, rhs);
case SHR: return IBINOP(lhs, >>, rhs);
case LT: return compare(lhs, rhs) < 0 ? true : false;
case LE: return IRELOP(lhs, <=, rhs);
case GE: return IRELOP(lhs, >=, rhs);
case GT: return IRELOP(lhs, > , rhs);
case LT: return compare(lhs, rhs) < 0 ? true : false;
case LE: return compare(lhs, rhs) <= 0 ? true : false;
case GE: return compare(lhs, rhs) >= 0 ? true : false;
case GT: return compare(lhs, rhs) > 0 ? true : false;
case EQ: return equal(lhs, rhs) ? true : false;
case NE: return equal(lhs, rhs) ? false : true;
case BAND: return IBINOP(lhs, & , rhs);

+ 13
- 1
test.txt 查看文件

@ -1,7 +1,9 @@
#!./main
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
int x = 21;
@ -36,7 +38,8 @@ int main(int argc, char **argv)
for (i = 0; i < 5; ++i) printf("%d\n", array[i]);
for (i = 0; i < 5; ++i) array[i] = i*i;
for (i = 0; i < 5; ++i) printf("%d\n", array[i]);
for (i = 0; i < 5; ++i) array[i] = array[i] * array[i];
for (i = 0; i < 5; ++i) array[i] = array[i] * array[i];
for (i = 0; i < 5; ++i) printf("%d\n", array[i]);
printf("%p\n", array);
@ -47,6 +50,15 @@ int main(int argc, char **argv)
while (p < array+5) printf("%d\n", *p++);
printf("%p\n", array);
printf("%p\n", &array);
printf("%p\n", &array[0]);
assert(array == &array);
assert(array == &array[0]);
assert(&array == array);
assert(&array[0] == array);
return 0;
}

正在加载...
取消
保存