Skip to content

Commit

Permalink
add print function
Browse files Browse the repository at this point in the history
  • Loading branch information
caipng committed Apr 25, 2024
1 parent f82773b commit 5857e55
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 4 deletions.
14 changes: 13 additions & 1 deletion src/builtins.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Identifier } from "./ast/types";
import { NO_EFFECTIVE_TYPE } from "./interpreter/effectiveTypeTable";
import { TemporaryObject } from "./interpreter/object";
import { TemporaryObject, stringify } from "./interpreter/object";
import { Runtime } from "./interpreter/runtime";
import { StashItem, isTemporaryObject } from "./interpreter/stash";
import { BIGINT_TO_BYTES, bytesToBigint } from "./typing/representation";
import {
FunctionType,
Type,
_any,
functionType,
int,
isArithmeticType,
Expand Down Expand Up @@ -73,4 +74,15 @@ export const BUILTIN_FUNCTIONS: Record<Identifier, BuiltinFunction> = {
rt.effectiveTypeTable.remove(n, blockSize);
},
},
print: {
type: functionType(voidType(), [{ identifier: "obj", type: _any() }]),
body: (rt: Runtime, args: StashItem[]) => {
if (args.length !== 1) throw "expected 1 arg for print";
const o = args[0];
if (!isTemporaryObject(o)) throw "expected object for print";
rt.appendToStdout(
stringify(o.bytes, o.typeInfo, rt.config.endianness) + "\n",
);
},
},
};
49 changes: 47 additions & 2 deletions src/interpreter/object.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { FunctionType } from "./../typing/types";
import {
FunctionType,
isArray,
isChar,
isPointer,
isScalarType,
isSigned,
isStructure,
} from "./../typing/types";
import { Identifier } from "./../ast/types";
import { ObjectTypeInfo } from "../typing/types";
import { checkValidByte } from "../utils";
import { checkValidByte, decimalAddressToHex } from "../utils";
import { Memory } from "../memory/memory";
import { Endianness } from "../config";
import { bytesToBigint } from "../typing/representation";

interface Identifiable {
identifier: Identifier;
Expand Down Expand Up @@ -113,3 +123,38 @@ export class RuntimeObject
this._identifier = i;
}
}

export const stringify = (
bytes: number[],
t: ObjectTypeInfo,
endianness: Endianness,
): string => {
if (bytes.length !== t.size)
throw new Error("number of bytes do not match type given");
if (isScalarType(t)) {
const n = bytesToBigint(bytes, isSigned(t), endianness);
if (isChar(t)) return "'" + encodeURI(String.fromCharCode(Number(n))) + "'";
if (isPointer(t)) {
if (n === BigInt(0)) return "NULL";
return decimalAddressToHex(Number(n));
}
return n.toString();
}
if (isArray(t)) {
const et = t.elementType;
const res = [];
for (let i = 0; i < t.size; i += et.size) {
res.push(stringify(bytes.slice(i, i + et.size), et, endianness));
}
return "[" + res.join(", ") + "]";
}
if (isStructure(t)) {
const res = [];
for (const i of t.members) {
const b = bytes.slice(i.relativeAddress, i.relativeAddress + i.type.size);
res.push(stringify(b, i.type, endianness));
}
return (t.tag || "") + "{" + res.join(", ") + "}";
}
return "?";
};
12 changes: 12 additions & 0 deletions src/interpreter/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export class RuntimeView {
heapMemUsage: number;
effectiveTypeTable: Record<number, EffectiveTypeTableEntry>;
initTable: InitializedTable;
stdout: string;

constructor(rt: Runtime) {
this.agenda = rt.agenda.getArr();
Expand All @@ -66,6 +67,7 @@ export class RuntimeView {
this.heapMemUsage = rt.heap.memUsage;
this.effectiveTypeTable = rt.effectiveTypeTable.getTable();
this.initTable = cloneDeep(rt.initTable);
this.stdout = rt.stdout;
}
}

Expand All @@ -85,6 +87,7 @@ export class Runtime {
private functions: [string, TypedCompoundStatement, FunctionType][];
private builtinFunctions: BuiltinFunction[];
private _exitCode: number | undefined;
private _stdout: string;
private _dataPtr: number;
private _textPtr: number;

Expand All @@ -111,6 +114,7 @@ export class Runtime {
this.functions = [];
this.builtinFunctions = [];
this._exitCode = undefined;
this._stdout = "";
this._dataPtr = config.memory.data.baseAddress;
this._textPtr = config.memory.text.baseAddress;

Expand Down Expand Up @@ -151,6 +155,14 @@ export class Runtime {
return this._exitCode;
}

public appendToStdout(s: string) {
this._stdout += s;
}

public get stdout() {
return this._stdout;
}

public addFunction(
identifier: string,
body: TypedCompoundStatement,
Expand Down
6 changes: 6 additions & 0 deletions src/typing/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ import {
Array,
Structure,
unsignedInt,
Type,
} from "./types";
import {
checkSimpleAssignmentConstraint,
Expand Down Expand Up @@ -1136,6 +1137,11 @@ const typePostfixExpressionNode = (
if (value.length !== ft.arity)
throw "function call has wrong number of arguments";
ft.parameterTypes.forEach((p, i) => {
if (p.type.type === Type._Any) {
if (!isObjectTypeInfo(value[i].typeInfo))
throw "expected parameter to have object type";
return;
}
if (
!checkSimpleAssignmentConstraint(
p.type,
Expand Down
18 changes: 17 additions & 1 deletion src/typing/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export enum Type {
Structure = "struct",
Function = "fn",
Pointer = "ptr",

_Any = "any object", // hack for inbuilt print function
}

export const getTypeName = (i: TypeInfo): string => {
Expand Down Expand Up @@ -73,7 +75,8 @@ export type ObjectType =
| Type.UnsignedLongLongInt
| Type.Array
| Type.Structure
| Type.Pointer;
| Type.Pointer
| Type._Any;

export type IncompleteType = Type.Void;

Expand Down Expand Up @@ -175,6 +178,19 @@ export interface ObjectTypeInfo extends BaseTypeInfo {
export const isObjectTypeInfo = (i: BaseTypeInfo): i is ObjectTypeInfo =>
!isIncompleteTypeInfo(i) && !isFunctionTypeInfo(i);

export interface _Any extends BaseTypeInfo {
type: Type._Any;
size: -1;
alignment: -1;
}

export const _any = (): _Any => ({
type: Type._Any,
size: -1,
alignment: -1,
isCompatible: () => false,
});

export interface _Bool extends ObjectTypeInfo {
type: Type._Bool;
size: typeof CHAR_SIZE;
Expand Down

0 comments on commit 5857e55

Please sign in to comment.