Skip to content

Commit

Permalink
implement memory model
Browse files Browse the repository at this point in the history
  • Loading branch information
caipng committed Mar 29, 2024
1 parent cb18953 commit 0110738
Show file tree
Hide file tree
Showing 27 changed files with 2,364 additions and 1,310 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,5 @@ dist/*.js
dist/*.js.map
lib/
.tscache
src/cparser.js
src/cparser.js
.vscode/settings.json
33 changes: 28 additions & 5 deletions parsers/cparser.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,9 @@ TypeSpecifier
/ INT
/ LONG
/ FLOAT
{ throwNotImplemented("floating type"); }
/ DOUBLE
{ throwNotImplemented("floating type"); }
/ SIGNED
/ UNSIGNED
/ BOOL
Expand All @@ -918,13 +920,18 @@ TypeSpecifier
StructOrUnionSpecifier
= StructOrUnion a:Identifier? LCUR b:StructDeclarationList RCUR
{
return makeNode("StructOrUnion", {
return makeNode("StructSpecifier", {
identifier: a,
declarationList: b
});
}
/ StructOrUnion a:Identifier
{ return makeNode("StructOrUnion", a); }
{
return makeNode("StructSpecifier", {
identifier: a,
declarationList: []
});
}

// (6.7.2.1) struct-or-union
StructOrUnion
Expand All @@ -938,15 +945,23 @@ StructDeclarationList

// (6.7.2.1) struct-declaration
StructDeclaration
= SpecifierQualifierList StructDeclaratorList? SEMI
= a:SpecifierQualifierList b:StructDeclaratorList? SEMI
{
return makeNode("Declaration", {
specifiers: a,
declaratorList: b || []
});
}
/ StaticAssertDeclaration
{ throwNotImplemented("static assert declaration"); }

// (6.7.2.1) specifier-qualifier-list
// Note the change from the standard to handle the TypedefName case
SpecifierQualifierList
= (TypeQualifier / AlignmentSpecifier)*
TypedefName
(TypeQualifier / AlignmentSpecifier)*
{ throwNotImplemented("typedef"); }
/ (
TypeSpecifier
/ TypeQualifier
Expand All @@ -955,12 +970,20 @@ SpecifierQualifierList

// (6.7.2.1) struct-declarator-list
StructDeclaratorList
= StructDeclarator (COMMA StructDeclarator)*
= a:StructDeclarator b:(COMMA b:StructDeclarator { return b; })*
{ return [a].concat(b || []); }

// (6.7.2.1) struct-declarator
StructDeclarator
= Declarator
= a:Declarator
{
return makeNode("InitDeclarator", {
declarator: a,
initializer: null
});
}
/ Declarator? COLON ConstantExpression
{ throwNotImplemented("bitfield"); }

// (6.7.2.2) enum-specifier
EnumSpecifier
Expand Down
57 changes: 50 additions & 7 deletions src/ast/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { FunctionType, TypeInfo } from "../typing/types";
import {
FunctionType,
ObjectTypeInfo,
ScalarType,
TypeInfo,
} from "../typing/types";

export interface PositionInfo {
offset: number;
Expand Down Expand Up @@ -38,7 +43,35 @@ export type ASTNode =
| PrimaryExprIdentifier
| PrimaryExprConstant
| PrimaryExprString
| PrimaryExprParenthesis;
| PrimaryExprParenthesis
| IntegerConstant;

export type TypedASTNode =
| TypedTranslationUnit
| TypedFunctionDefinition
| TypedDeclaration
| TypedInitDeclarator
| TypedCompoundStatement
| TypedJumpStatementReturn
| EmptyExpressionStatement
| TypedCommaOperator
| TypedAssignmentExpressionNode
| TypedConditionalExpressionNode
| TypedBinaryExpressionNode
| TypedUnaryExpressionIncr
| TypedUnaryExpressionDecr
| TypedUnaryExpressionNode
| TypedPostfixExpressionNode
| TypedArraySubscriptingOp
| TypedFunctionCallOp
| TypedPointerMemberOp
| TypedStructMemberOp
| TypedPostfixIncrementOp
| TypedPostfixDecrementOp
| TypedPrimaryExprIdentifier
| TypedPrimaryExprConstant
| TypedPrimaryExprString
| TypedPrimaryExprParenthesis;

export interface TranslationUnit extends BaseNode {
type: "TranslationUnit";
Expand Down Expand Up @@ -95,11 +128,19 @@ export type TypeSpecifier =
| "short"
| "int"
| "long"
| "float"
| "double"
| "signed"
| "unsigned"
| "_Bool";
| "_Bool"
| StructSpecifier;

export interface StructSpecifier extends BaseNode {
type: "StructSpecifier";
identifier: Identifier | null;
declarationList: Declaration[];
}

export const isStructSpecifier = (i: TypeSpecifier): i is StructSpecifier =>
typeof i === "object";

export interface InitDeclarator extends BaseNode {
type: "InitDeclarator";
Expand All @@ -110,7 +151,7 @@ export interface InitDeclarator extends BaseNode {
export interface TypedInitDeclarator extends BaseNode {
type: "InitDeclarator";
identifier: Identifier;
typeInfo: TypeInfo;
typeInfo: ObjectTypeInfo;
initializer: TypedInitializer | null;
}

Expand Down Expand Up @@ -146,7 +187,7 @@ export const isIdentifierDeclaratorPart = (

export interface ArrayDeclaratorPart {
partType: "array";
length: number;
length: IntegerConstant;
}

export const isArrayDeclaratorPart = (
Expand Down Expand Up @@ -568,6 +609,7 @@ export const isPrimaryExprIdentifier = (
export interface TypedPrimaryExprIdentifier extends TypedExpressionBaseNode {
type: "PrimaryExprIdentifier";
value: Identifier;
typeInfo: ObjectTypeInfo | FunctionType;
}

export interface PrimaryExprConstant extends BaseNode {
Expand Down Expand Up @@ -630,6 +672,7 @@ export interface IntegerConstant extends BaseNode {
export interface TypedIntegerConstant extends TypedExpressionBaseNode {
type: "IntegerConstant";
value: bigint;
typeInfo: ScalarType;
}

export const isTypedIntegerConstant = (
Expand Down
40 changes: 40 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export interface MemoryRegionConfig {
size: number;
baseAddress: number;
}

export interface MemoryConfig {
stack: MemoryRegionConfig;
heap: MemoryRegionConfig;
data: MemoryRegionConfig;
text: MemoryRegionConfig;
}

export type Endianness = "little" | "big";

export interface RuntimeConfig {
memory: MemoryConfig;
endianness: Endianness;
}

export const DEFAULT_CONFIG: RuntimeConfig = {
memory: {
stack: {
baseAddress: 1e6,
size: 5e5,
},
heap: {
baseAddress: 2e6,
size: 5e5,
},
data: {
baseAddress: 3e6,
size: 5e5,
},
text: {
baseAddress: 4e6,
size: 5e5,
},
},
endianness: "little",
};
20 changes: 13 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { parse, errorMessage } from "pegjs-util";
import * as cparser from "./cparser";
import { evaluate, evaluateNext } from "./interpreter/interpreter";
import { TranslationUnit } from "./ast/types";
import { Runtime } from "./interpreter/types";
import { TranslationUnit, TypedTranslationUnit } from "./ast/types";
import { typeTranslationUnit } from "./typing/main";
import { Runtime } from "./interpreter/runtime";
import { DEFAULT_CONFIG } from "./config";

export default {
parseProgram(source: string): TranslationUnit {
Expand All @@ -12,11 +13,16 @@ export default {
}
return res.ast as TranslationUnit;
},
typeCheck(t: TranslationUnit): TypedTranslationUnit {
try {
return typeTranslationUnit(t);
} catch (err) {
throw new Error("" + err);
}
},
run(source: string): Runtime {
const program = this.parseProgram(source);
return evaluate(program);
},
next(rt: Runtime): Runtime {
return evaluateNext(rt);
const typedTranslationUnit = this.typeCheck(program);
return new Runtime(typedTranslationUnit, DEFAULT_CONFIG);
},
};
48 changes: 48 additions & 0 deletions src/interpreter/agenda.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { has } from "lodash";
import {
TypedTranslationUnit,
TypedPrimaryExprIdentifier,
TypedASTNode,
} from "../ast/types";
import { functionType, int } from "../typing/types";
import { Stack } from "../utils";
import { exitInstruction, callInstruction, Instruction } from "./instructions";

export type AgendaItem = TypedASTNode | Instruction;

export function isASTNode(i: AgendaItem): i is TypedASTNode {
return has(i, "src");
}

export function isInstruction(i: AgendaItem): i is Instruction {
return !isASTNode(i);
}

export class Agenda extends Stack<AgendaItem> {
constructor(program: TypedTranslationUnit) {
super();

const mainFunction: TypedPrimaryExprIdentifier = {
type: "PrimaryExprIdentifier",
start: {
offset: 0,
column: 0,
line: 0,
},
end: {
offset: 1,
column: 1,
line: 0,
},
src: "main",
value: "main",
lvalue: false,
typeInfo: functionType(int(), []),
};

this.push(exitInstruction());
this.push(callInstruction(0));
this.push(mainFunction);
this.push(program);
}
}
Loading

0 comments on commit 0110738

Please sign in to comment.