Skip to content

Commit

Permalink
✨ Implement the full-version of StringNative native group
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkChenYutian committed Jul 22, 2022
1 parent 88e099b commit 7b50909
Show file tree
Hide file tree
Showing 12 changed files with 523 additions and 26 deletions.
5 changes: 1 addition & 4 deletions src/application.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
@media screen and (min-width: 810px) {
div.code-editor {
max-width: calc(50vw - 1.5rem);
}
div.io-area {
max-width: calc(50vw - 1.5rem);
max-width: min(calc(50vw - 1.5rem), 50rem);
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/components/debug_console/debug_utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,13 @@ export function render_c0_value(v: C0Value<"value">): string {
case "int":
return "" + c0_cvt2_js_value(v);
case "char":
return "'" + c0_cvt2_js_value(v) + "'";
const string = c0_cvt2_js_value(v);
if (string === "\n") {
return "'\\n'";
} else if (string === "\0") {
return "'\\0'";
}
return "'" + string + "'";
}
}

Expand Down
9 changes: 7 additions & 2 deletions src/components/debug_console/reactflow/struct_node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { internal_error } from "../../../utility/errors";
import { calculate_entry_height } from "../graphical_utility";
import { isNullPtr } from "../../../vm_core/utility/pointer_ops";
import { loadString } from "../../../vm_core/utility/string_utility";
import { heapNodeTargetHandleID } from "../graph_builder";
import { heapNodeTargetHandleID, structSrcHandleID } from "../graph_builder";

export default class C0StructNode extends React.Component<NodeProps<C0StructNodeData>> {
render_content(mem: C0HeapAllocator, type: C0Type<"ptr">, value: C0Pointer, typeRecord: Map<string, Map<number, Struct_Type_Record>>) {
Expand Down Expand Up @@ -51,7 +51,12 @@ export default class C0StructNode extends React.Component<NodeProps<C0StructNode
<p key={"s-val-value-" + entry.offset} className="dbg-frame-content">{render_content}</p>
{
entry.value.type.type === "ptr" && !isNullPtr(entry.value.value)?
<Handle type="source" key={"s-val-ptr-" + entry.offset} id={"s-val-ptr-" + entry.offset} position={Position.Right} style={{ top: calculate_entry_height(i, "struct"), right: "1.2rem" }}/>
<Handle type="source"
key={structSrcHandleID(entry.offset)}
id={structSrcHandleID(entry.offset)}
position={Position.Right}
style={{ top: calculate_entry_height(i, "struct"), right: "1.2rem" }}
/>
: null
}
</>
Expand Down
11 changes: 2 additions & 9 deletions src/components/debug_console/tabular_c0value.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ import React from "react";
import { faCaretDown, faCaretRight } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

import { c0_cvt2_js_value } from "../../vm_core/utility/c0_value";
import { isNullPtr, read_ptr } from "../../vm_core/utility/pointer_ops";
import { loadString } from "../../vm_core/utility/string_utility";

import { derefValue, expandArrayValue, expandStructValue } from "./debug_utility";
import { derefValue, expandArrayValue, expandStructValue, render_c0_value } from "./debug_utility";

export default class C0ValueTabularDisplay extends React.Component<
C0ValueTabularDisplayProps,
Expand Down Expand Up @@ -255,13 +254,7 @@ export default class C0ValueTabularDisplay extends React.Component<

render(): React.ReactNode {
if (this.props.value.type.type === "value") {
switch (this.props.value.type.value) {
case "bool":
case "int":
return <p>{"" + c0_cvt2_js_value(this.props.value as C0Value<"value">)}</p>
case "char":
return <p>'{c0_cvt2_js_value(this.props.value as C0Value<"value">)}'</p>
}
return <p>{render_c0_value(this.props.value as C0Value<"value">)}</p>
}
if (this.props.value.type.type === "string") {
return <p>"{loadString(this.props.value as C0Value<"string">, this.props.mem)}"</p>
Expand Down
2 changes: 1 addition & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ globalThis.UI_ERR_DISPLAY_TIME_SEC = 4;
globalThis.UI_WARN_DISPLAY_TIME_SEC = 4;
globalThis.UI_OK_DISPLAY_TIME_SEC = 1;

globalThis.COMPILER_BACKEND_URL = "http://172.18.90.173:8081/compile";
globalThis.COMPILER_BACKEND_URL = "http://127.0.0.1:8081/compile";

globalThis.C0_ENVIR_MODE = "web";
globalThis.C0_MAX_RECURSION = 999;
Expand Down
100 changes: 92 additions & 8 deletions src/vm_core/native/native_interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ function nativeFuncMapping(index: number): C0Native | undefined {
return {
functionType: "NATIVE_FLUSH",
numArgs: 0,
f: nativeNotImplemented,
f: (UIHook: ReactUIHook, mem: C0HeapAllocator) => {
return js_cvt2_c0_value(IONative.c0_flush());
}
};
/**
* TODO:
Expand Down Expand Up @@ -341,21 +343,58 @@ function nativeFuncMapping(index: number): C0Native | undefined {
return {
functionType: "NATIVE_CHAR_CHR",
numArgs: 0,
f: nativeNotImplemented,
f: (
UIHooks: ReactUIHook,
mem: C0HeapAllocator,
arg1: C0Value<C0TypeClass>) => {
if (TypeUtil.maybeValueType(arg1)) {
return js_cvt2_c0_value(
StringNative.c0_char_chr(arg1)
);
}
throw new vm_error("NATIVE_CHAR_CHR only accepts (value) as input");
},
};
}
case 92: {
return {
functionType: "NATIVE_CHAR_ORD",
numArgs: 0,
f: nativeNotImplemented,
f: (
UIHooks: ReactUIHook,
mem: C0HeapAllocator,
arg1: C0Value<C0TypeClass>) => {
if (TypeUtil.maybeValueType(arg1)) {
return js_cvt2_c0_value(
StringNative.c0_char_ord(arg1)
);
}
throw new vm_error("NATIVE_CHAR_ORD only accepts (value) as input");
},
};
}
case 93: {
return {
functionType: "NATIVE_STRING_CHARAT",
numArgs: 0,
f: nativeNotImplemented,
f: (
UIHooks: ReactUIHook,
mem: C0HeapAllocator,
arg1: C0Value<C0TypeClass>,
arg2: C0Value<C0TypeClass>
) => {
if (
TypeUtil.maybeStringType(arg1) &&
TypeUtil.maybeValueType(arg2)
) {
return js_cvt2_c0_value(
StringNative.c0_string_charat(mem, arg1, arg2)
);
}
throw new vm_error(
"NATIVE_STRING_CHARAT only accepts (string, value) as input"
);
},
};
}
case 94: {
Expand Down Expand Up @@ -512,14 +551,50 @@ function nativeFuncMapping(index: number): C0Native | undefined {
return {
functionType: "NATIVE_STRING_SUB",
numArgs: 0,
f: nativeNotImplemented,
f: (
UIHook: ReactUIHook,
mem: C0HeapAllocator,
arg1: C0Value<C0TypeClass>,
arg2: C0Value<C0TypeClass>,
arg3: C0Value<C0TypeClass>,
) => {
if (
TypeUtil.maybeStringType(arg1) &&
TypeUtil.maybeValueType(arg2) &&
TypeUtil.maybeValueType(arg3)
) {
return build_c0_stringValue(
StringNative.c0_string_sub(mem, arg1, arg2, arg3)
);
}
throw new vm_error(
"NATIVE_STRING_SUB only accepts (string, value, value) as input"
);
},
};
}
case 103: {
return {
functionType: "NATIVE_STRING_TERMINATED",
numArgs: 0,
f: nativeNotImplemented,
f: (
UIHook: ReactUIHook,
mem: C0HeapAllocator,
arg1: C0Value<C0TypeClass>,
arg2: C0Value<C0TypeClass>
) => {
if (
TypeUtil.maybePointerType(arg1) &&
TypeUtil.maybeValueType(arg2)
) {
return js_cvt2_c0_value(
StringNative.c0_string_terminated(mem, arg1, arg2)
);
}
throw new vm_error(
"NATIVE_STRING_TERMINATED only accepts (ptr, value) as input"
);
},
};
}
case 104: {
Expand All @@ -535,7 +610,7 @@ function nativeFuncMapping(index: number): C0Native | undefined {
);
}
throw new vm_error(
"NATIVE_STRING_TO_CHARARRAY only accepts pointer as input"
"NATIVE_STRING_TO_CHARARRAY only accepts (string) as input"
);
},
};
Expand All @@ -544,7 +619,16 @@ function nativeFuncMapping(index: number): C0Native | undefined {
return {
functionType: "NATIVE_STRING_TOLOWER",
numArgs: 0,
f: nativeNotImplemented,
f: (UIHook: ReactUIHook, mem: C0HeapAllocator, arg1: C0Value<C0TypeClass>) => {
if (TypeUtil.maybeStringType(arg1)) {
return build_c0_stringValue(
StringNative.c0_string_tolower(mem, arg1)
);
}
throw new vm_error(
"NATIVE_STRING_TOLOWER only accepts (string) as input"
);
},
};
}
default:
Expand Down
4 changes: 4 additions & 0 deletions src/vm_core/native/native_io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,7 @@ export function c0_readline(mem: C0HeapAllocator): C0Pointer {
const userInput = prompt("C0VM.ts Input:");
return allocate_js_string(mem, userInput === null ? "" : userInput);
}

export function c0_flush(): boolean {
return true;
}
81 changes: 80 additions & 1 deletion src/vm_core/native/native_strings.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
/**
* @author Yutian Chen <yutianch@andrew.cmu.edu>
* @Description TypeScript implementation of string native functions in C0VM.
*
* Source:
* cc0/bare/cstr.c
* cc0/libs/string/string.c
*/

import { c0_cvt2_js_value } from "../utility/c0_value";
import { vm_error } from "../../utility/errors";
import { c0_value_error, vm_error } from "../../utility/errors";
import { read_ptr } from "../utility/pointer_ops";
import { loadString, allocate_js_string } from "../utility/string_utility";
import { expandArrayValue } from "../../components/debug_console/debug_utility";
import { String2Type } from "../types/c0type_utility";

/**
* Compare two "string" objects
Expand Down Expand Up @@ -165,3 +171,76 @@ export function c0_string_from_chararray(
}
return allocate_js_string(mem, str);
}

export function c0_string_charat(
mem: C0HeapAllocator,
arg1: C0Value<Maybe<"string">>,
arg2: C0Value<Maybe<"value">>
): string {
const str = loadString(arg1, mem);
// Force cast
arg2.type = {type: "value", value: "int"};

const idx = c0_cvt2_js_value(arg2) as number;
if (idx < 0 || idx >= str.length) throw new c0_value_error("c0_string_charat: index out of bound");
return str[idx];
}

export function c0_string_sub(
mem: C0HeapAllocator,
arg1: C0Value<Maybe<"string">>,
arg2: C0Value<Maybe<"value">>,
arg3: C0Value<Maybe<"value">>
): C0Pointer {
const str = loadString(arg1, mem);
// Force cast
arg2.type = {type: "value", value: "int"};
arg3.type = {type: "value", value: "int"};

const lidx = c0_cvt2_js_value(arg2) as number;
const ridx = c0_cvt2_js_value(arg3) as number;
if (lidx < 0) throw new c0_value_error("c0_string_sub: start_idx < 0");
if (ridx > str.length) throw new c0_value_error("c0_string_sub: end_idx > string length");
if (lidx > ridx) throw new c0_value_error("c0_string_sub: start_idx > end_idx");
if (lidx === ridx) return allocate_js_string(mem, "");
return allocate_js_string(mem, str.slice(lidx, ridx));
}


export function c0_string_terminated(
mem: C0HeapAllocator,
arg1: C0Value<Maybe<"ptr">>,
arg2: C0Value<Maybe<"value">>
): boolean {
// Force cast
arg1.type = String2Type("char[]") as C0Type<"ptr">;
arg2.type = String2Type("int") as C0Type<"value">;

const str = expandArrayValue(mem, arg1 as C0Value<"ptr">);

const n = c0_cvt2_js_value(arg2);
for (let i = 0; i < str.length && i < n; i ++) {
if (c0_cvt2_js_value(str[i] as C0Value<"value">) === '\0') {
return true;
}
}
return false;
}

export function c0_char_ord(arg1: C0Value<Maybe<"value">>): number {
return c0_cvt2_js_value(arg1).toString().charCodeAt(0);
}

export function c0_char_chr(arg1: C0Value<Maybe<"value">>): string {
// Force cast
arg1.type = String2Type("int") as C0Type<"value">;

const n = c0_cvt2_js_value(arg1) as number;
if (n < 0 || n > 127) throw new c0_value_error("c0_char_chr: only ASCII code [0, 127] is supported.");
return String.fromCharCode(n);
}

export function c0_string_tolower(mem: C0HeapAllocator, arg1: C0Value<Maybe<"string">>): C0Pointer {
const s = loadString(arg1, mem);
return allocate_js_string(mem, s.toLowerCase());
}
13 changes: 13 additions & 0 deletions tests/tbuf/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# WARNING

IF YOU ARE CURRENTLY ENROLLED IN 15-122, DO NOT OPEN ANY FILE
IN THIS DIRECTORY. DOING SO WILL LEAD TO ACADEMIC INTEGRITY
VIOLATION.

THIS FILE IS HERE ONLY FOR TESTING PURPOSE.

# YOU HAVE BEEN WARNED

Compiling and running the tbuf tests:
% cc0 -W -w -b -o tbuf-test.bc0 tbuf.c0 tbuf-test.c0 test-main.c0
% ./tbuf-test
Loading

0 comments on commit 7b50909

Please sign in to comment.