Initial commit :3
This commit is contained in:
commit
015ec69720
192
.clang-format
Normal file
192
.clang-format
Normal file
@ -0,0 +1,192 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: Microsoft
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveMacros: None
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: false
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
QualifierAlignment: Leave
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
PackConstructorInitializers: BinPack
|
||||
BasedOnStyle: ''
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseLabels: false
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentRequires: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
LambdaBodyIndentation: Signature
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Right
|
||||
PPIndentWidth: -1
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: Both
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- NS_SWIFT_NAME
|
||||
- CF_SWIFT_NAME
|
||||
...
|
||||
|
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
.trash/
|
||||
.dev/
|
||||
|
||||
spec.md
|
||||
default.nix
|
||||
|
||||
lbr
|
||||
|
||||
std/
|
11
LICENSE
Normal file
11
LICENSE
Normal file
@ -0,0 +1,11 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
7
Makefile
Normal file
7
Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
CC=clang
|
||||
|
||||
all:
|
||||
$(CC) -o lbr -O2 -Wall -Wextra -Wpedantic src/*.c
|
||||
|
||||
test:
|
||||
./lbr tests/test.lb
|
9
src/config.h
Normal file
9
src/config.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#define STACK_SIZE 65535
|
||||
#define PROGRAM_MAXSIZE 65535
|
||||
#define MAX_LABELS 256
|
||||
#define MAX_MODULES 256
|
||||
#define MAX_BF_LOOPS 256
|
||||
|
||||
#define DEBUG_MODE 0
|
572
src/execute.c
Normal file
572
src/execute.c
Normal file
@ -0,0 +1,572 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "execute.h"
|
||||
#include "stack.h"
|
||||
|
||||
#define NAME stack->program[stack->program_counter].name
|
||||
#define DATA stack->program[stack->program_counter].data
|
||||
#define ARG stack->program[stack->program_counter].arg
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MPUSH = '>',
|
||||
MDROP = '$',
|
||||
MDUP = ':',
|
||||
MSWAP = '\\',
|
||||
MINC = '+',
|
||||
MDEC = '-',
|
||||
|
||||
PPIPE = '|',
|
||||
PREFLECT = '^'
|
||||
} OP;
|
||||
|
||||
static void prefix_operator(Stack *stack, char op)
|
||||
{
|
||||
if (NAME[0] != '@' && (NAME[1] == '\0' || NAME[1] == '\n'))
|
||||
{
|
||||
printf("%c\n", op);
|
||||
kms(stack, "Invalid usage of prefix operators");
|
||||
}
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case PPIPE:
|
||||
NAME++;
|
||||
|
||||
DATA = stack_pop(stack);
|
||||
|
||||
break;
|
||||
|
||||
case PREFLECT:
|
||||
NAME++;
|
||||
|
||||
if (NAME[0] != '#' && NAME[0] != '$')
|
||||
printf("%s %i", NAME, DATA);
|
||||
|
||||
else if (!strcmp(ARG, "\n"))
|
||||
printf("%s", NAME);
|
||||
|
||||
else
|
||||
printf("%s %s", NAME, ARG);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void expression(Stack *stack, char *code)
|
||||
{
|
||||
uint16_t ax, ax2;
|
||||
|
||||
for (uint16_t i = 0; code[i] != '\0'; i++)
|
||||
{
|
||||
switch (code[i])
|
||||
{
|
||||
case MPUSH:
|
||||
stack_push(stack, 0);
|
||||
break;
|
||||
|
||||
case MDROP:
|
||||
stack_pop(stack);
|
||||
break;
|
||||
|
||||
case MDUP:
|
||||
stack_push(stack, stack_peek(stack));
|
||||
break;
|
||||
|
||||
case MSWAP:
|
||||
ax = stack_pop(stack);
|
||||
ax2 = stack_pop(stack);
|
||||
stack_push(stack, ax);
|
||||
stack_push(stack, ax2);
|
||||
break;
|
||||
|
||||
case MINC:
|
||||
ax = stack_pop(stack);
|
||||
stack_push(stack, ax + 1);
|
||||
break;
|
||||
|
||||
case MDEC:
|
||||
ax = stack_pop(stack);
|
||||
stack_push(stack, ax - 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("INVALID EXPRESSION: UNKNOWN OPERATOR '%c'\n", code[i]);
|
||||
kms(stack, "INVALID EXPRESSION");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void find_labels(Stack *stack)
|
||||
{
|
||||
for (; stack->program_counter < stack->program_size; stack->program_counter++)
|
||||
{
|
||||
if (NAME[0] == '@')
|
||||
{
|
||||
if (DATA > MAX_LABELS)
|
||||
{
|
||||
printf("INVALID LABEL: %i\n", DATA);
|
||||
kms(stack, "INVALID LABEL");
|
||||
}
|
||||
|
||||
if (stack->labels[DATA] != -1)
|
||||
{
|
||||
printf("LABEL ALREADY DEFINED: %i\n", DATA);
|
||||
kms(stack, "LABEL ALREADY DEFINED");
|
||||
}
|
||||
|
||||
if (DATA == 0)
|
||||
{
|
||||
stack->labels[0] = stack->program_counter;
|
||||
continue;
|
||||
}
|
||||
|
||||
stack->labels[DATA] = stack->program_counter;
|
||||
}
|
||||
}
|
||||
if (stack->labels[0] != -1)
|
||||
stack->program_counter = stack->labels[0];
|
||||
else
|
||||
stack->program_counter = 0;
|
||||
}
|
||||
|
||||
void execute(Stack *stack, Stack *originstack, char *modname)
|
||||
{
|
||||
find_labels(stack);
|
||||
|
||||
for (; stack->program_counter < stack->program_size; stack->program_counter++)
|
||||
{
|
||||
prefix_operator(stack, NAME[0]);
|
||||
|
||||
if (NAME[0] == '@')
|
||||
continue;
|
||||
|
||||
// Stack operations
|
||||
|
||||
if (!strcmp(NAME, "push")) // arg <uint16>
|
||||
{
|
||||
stack_push(stack, DATA);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "pop"))
|
||||
{
|
||||
stack_pop(stack);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "dup"))
|
||||
{
|
||||
stack_push(stack, stack_peek(stack));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "swap"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, a);
|
||||
stack_push(stack, b);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "pick"))
|
||||
{
|
||||
uint16_t arg = stack_pop(stack);
|
||||
|
||||
if (arg >= stack->pointer)
|
||||
kms(stack, "ATTEMPTED TO PICK BELOW STACK");
|
||||
|
||||
stack_push(stack, stack->memory[stack->pointer - arg - 1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Math
|
||||
|
||||
if (!strcmp(NAME, "add"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, b + a);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "sub"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, b - a);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "mul"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, b * a);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "div"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, b / a);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "mod"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, b % a);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Logic
|
||||
|
||||
if (!strcmp(NAME, "and"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, a && b);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "or"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, a || b);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "xor"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, !a != !b);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "nand"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, !(a && b));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "not"))
|
||||
{
|
||||
stack_push(stack, !stack_pop(stack));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Bitwise
|
||||
|
||||
if (!strcmp(NAME, "band"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, a & b);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "bor"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, a | b);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "bxor"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, a ^ b);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "bnand"))
|
||||
{
|
||||
uint16_t a = stack_pop(stack);
|
||||
uint16_t b = stack_pop(stack);
|
||||
stack_push(stack, ~(a & b));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "bnot"))
|
||||
{
|
||||
stack_push(stack, ~stack_pop(stack));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Flow control
|
||||
|
||||
if (!strcmp(NAME, "jmp")) // arg <uint16>
|
||||
{
|
||||
if (stack->labels[DATA] == -1)
|
||||
{
|
||||
printf("UNKNOWN LABEL: %i\n", DATA);
|
||||
kms(stack, "UNKNOWN LABEL");
|
||||
}
|
||||
|
||||
stack->program_counter = stack->labels[DATA];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "jnz")) // arg <uint16>
|
||||
{
|
||||
if (stack->labels[DATA] == -1)
|
||||
{
|
||||
printf("UNKNOWN LABEL: %i\n", DATA);
|
||||
kms(stack, "UNKNOWN LABEL");
|
||||
}
|
||||
|
||||
if (stack_pop(stack) != 0)
|
||||
stack->program_counter = stack->labels[DATA];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "jz")) // arg <uint16>
|
||||
{
|
||||
if (stack->labels[DATA] == -1)
|
||||
{
|
||||
printf("UNKNOWN LABEL: %i\n", DATA);
|
||||
kms(stack, "UNKNOWN LABEL");
|
||||
}
|
||||
|
||||
if (stack_pop(stack) == 0)
|
||||
stack->program_counter = stack->labels[DATA];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "kjnz")) // arg <uint16>
|
||||
{
|
||||
if (stack->labels[DATA] == -1)
|
||||
{
|
||||
printf("UNKNOWN LABEL: %i\n", DATA);
|
||||
kms(stack, "UNKNOWN LABEL");
|
||||
}
|
||||
|
||||
if (stack_peek(stack) != 0)
|
||||
stack->program_counter = stack->labels[DATA];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "kjz")) // arg <uint16>
|
||||
{
|
||||
if (stack->labels[DATA] == -1)
|
||||
{
|
||||
printf("UNKNOWN LABEL: %i\n", DATA);
|
||||
kms(stack, "UNKNOWN LABEL");
|
||||
}
|
||||
|
||||
if (stack_peek(stack) == 0)
|
||||
stack->program_counter = stack->labels[DATA];
|
||||
continue;
|
||||
}
|
||||
|
||||
// I/O
|
||||
|
||||
if (!strcmp(NAME, "putc"))
|
||||
{
|
||||
putchar(stack_pop(stack));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "getc"))
|
||||
{
|
||||
stack_push(stack, getchar());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "scan"))
|
||||
{
|
||||
uint16_t num;
|
||||
scanf("%hu", &num);
|
||||
stack_push(stack, num);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "meow"))
|
||||
{
|
||||
printf("%i\n", stack_pop(stack));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "$println")) // arg <string>
|
||||
{
|
||||
printf("%s\n", ARG);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "#println")) // arg <string>
|
||||
{
|
||||
printf("%s\n", ARG);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "$print")) // arg <string>
|
||||
{
|
||||
printf("%s", ARG);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "#print")) // arg <const>
|
||||
{
|
||||
printf("%s", ARG);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Modules
|
||||
|
||||
if (!strcmp(NAME, "args")) // arg <uint16>
|
||||
{
|
||||
if (!originstack)
|
||||
kms(stack, "ATTEMPTED TO USE ARGS IN THE MAIN MODULE");
|
||||
|
||||
if (DATA > STACK_SIZE)
|
||||
kms(stack, "ATTEMPTED TO POP MORE THAN STACK_SIZE ARGUMENTS");
|
||||
|
||||
if (DATA == 0)
|
||||
DATA = stack_pop(originstack);
|
||||
|
||||
uint16_t ddata = DATA;
|
||||
|
||||
while (ddata != 0)
|
||||
{
|
||||
stack_push(stack, stack_pop(originstack));
|
||||
ddata--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "#exec")) // arg <const>
|
||||
{
|
||||
|
||||
if (!strcmp(ARG, modname))
|
||||
{
|
||||
printf("MODULE %s: CAN'T EXECUTE ITSELF\n", ARG);
|
||||
kms(stack, "CAN'T EXECUTE ITSELF");
|
||||
}
|
||||
|
||||
FILE *file = fopen(ARG, "r");
|
||||
if (!file)
|
||||
{
|
||||
printf("ERROR OPENING MODULE: %s\n", ARG);
|
||||
kms(stack, "ERROR OPENING MODULE");
|
||||
}
|
||||
|
||||
DATA = DATA ? DATA : STACK_SIZE;
|
||||
|
||||
Stack *tempstack = program_init(DATA);
|
||||
|
||||
parse_and_process(tempstack, file);
|
||||
|
||||
fclose(file);
|
||||
|
||||
execute(tempstack, stack, ARG);
|
||||
|
||||
for (int i = 0; i < tempstack->pointer; i++)
|
||||
stack_push(stack, tempstack->memory[i]);
|
||||
|
||||
free(tempstack);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Self-modifying
|
||||
|
||||
if (!strcmp(NAME, "#insert")) // arg <const>
|
||||
{
|
||||
if (ARG[0] == '#' || ARG[0] == '$')
|
||||
kms(stack, "ATTEMPTED TO INSERT A HASH/STRING-INSTRUCTION");
|
||||
|
||||
if (ARG[0] == '\n')
|
||||
kms(stack, "ATTEMPTED TO INSERT AN EMPTY CONSTANT");
|
||||
|
||||
if (ARG[0] == '@' && ARG[1] == ' ')
|
||||
kms(stack, "ATTEMPTED TO INSERT A LABEL");
|
||||
|
||||
stack->program[stack->program_size++] = (Instruction){ARG, "\n", DATA};
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special
|
||||
|
||||
if (!strcmp(NAME, "dump"))
|
||||
{
|
||||
for (int i = 0; i < stack->pointer; i++)
|
||||
printf("%d: %d\n", i, stack->memory[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "size"))
|
||||
{
|
||||
int i = 0;
|
||||
while (i < stack->pointer)
|
||||
i++;
|
||||
|
||||
stack_push(stack, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "maxsize"))
|
||||
{
|
||||
stack_push(stack, stack->stacksize);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "#expr")) // arg <const>
|
||||
{
|
||||
expression(stack, ARG);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "nop"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "quit"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp(NAME, "exit"))
|
||||
{
|
||||
exit(stack_pop(stack));
|
||||
}
|
||||
|
||||
// Platform-specific
|
||||
|
||||
#ifdef __unix__
|
||||
|
||||
if (!strcmp(NAME, "_unix_random"))
|
||||
{
|
||||
srand(getc(fopen("/dev/urandom", "r")));
|
||||
stack_push(stack, rand() % stack_pop(stack));
|
||||
continue;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// LBR-SPECIFIC
|
||||
printf("UNKNOWN INSTRUCTION: %s\n", NAME);
|
||||
kms(stack, "UNKNOWN INSTRUCTION");
|
||||
}
|
||||
}
|
||||
|
||||
#undef NAME
|
||||
#undef ARG
|
||||
#undef DATA
|
3
src/execute.h
Normal file
3
src/execute.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include "stack.h"
|
||||
|
||||
void execute(Stack *stack, Stack *originstack, char *modname);
|
34
src/main.c
Normal file
34
src/main.c
Normal file
@ -0,0 +1,34 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "execute.h"
|
||||
#include "stack.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [FILE]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Stack *stack = program_init(STACK_SIZE);
|
||||
|
||||
FILE *file = fopen(argv[1], "r");
|
||||
if (!file)
|
||||
{
|
||||
perror("fopen()");
|
||||
return 1;
|
||||
}
|
||||
|
||||
parse_and_process(stack, file);
|
||||
|
||||
fclose(file);
|
||||
|
||||
execute(stack, (void *)0, argv[1]);
|
||||
|
||||
return 0;
|
||||
}
|
100
src/stack.c
Normal file
100
src/stack.c
Normal file
@ -0,0 +1,100 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "stack.h"
|
||||
|
||||
Stack *program_init(uint16_t stacksize)
|
||||
{
|
||||
Stack *stack = malloc(sizeof(&stack) + sizeof(Instruction) * PROGRAM_MAXSIZE + sizeof(int16_t) * MAX_LABELS +
|
||||
sizeof(uint16_t) * stacksize);
|
||||
|
||||
stack->stacksize = stacksize;
|
||||
|
||||
for (unsigned int i = 0; i < MAX_LABELS; i++)
|
||||
stack->labels[i] = -1; // костыль ебанный
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
void stack_push(Stack *stack, uint16_t data)
|
||||
{
|
||||
if (stack->pointer > STACK_SIZE)
|
||||
kms(stack, "STACK OVERFLOW");
|
||||
stack->memory[stack->pointer++] = data;
|
||||
}
|
||||
|
||||
uint16_t stack_pop(Stack *stack)
|
||||
{
|
||||
if (stack->pointer <= 0)
|
||||
kms(stack, "STACK UNDERFLOW");
|
||||
return stack->memory[--stack->pointer];
|
||||
}
|
||||
|
||||
uint16_t stack_peek(Stack *stack)
|
||||
{
|
||||
return stack->memory[stack->pointer - 1];
|
||||
}
|
||||
|
||||
void kms(Stack *stack, const char *err)
|
||||
{
|
||||
if (DEBUG_MODE)
|
||||
for (int i = 0; i < stack->pointer; i++)
|
||||
printf("%d: %d\n", i, stack->memory[i]);
|
||||
|
||||
fprintf(stderr, "%s", err);
|
||||
free(stack);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void parse_and_process(Stack *stack, FILE *file)
|
||||
{
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while (getline(&line, &len, file) != -1)
|
||||
{
|
||||
if (line[0] == ';')
|
||||
continue;
|
||||
|
||||
line[strcspn(line, "\n")] = 0;
|
||||
unsigned long com = strcspn(line, ";");
|
||||
if (com)
|
||||
line[com] = '\0'; // шоб пропустил комментарий
|
||||
|
||||
Instruction inst;
|
||||
memset(&inst, 0, sizeof(inst)); // обнуляем структуру на всякий если
|
||||
// вернутся старые значения
|
||||
|
||||
inst.name = strtok(line, " ");
|
||||
if (!inst.name)
|
||||
continue;
|
||||
|
||||
if (inst.name[0] == 9)
|
||||
{
|
||||
printf("Tabs are not allowed!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *data = strtok(NULL, "");
|
||||
|
||||
if (!data)
|
||||
data = 0;
|
||||
else if (inst.name[0] == '#' || inst.name[1] == '#')
|
||||
inst.arg = strtok(data, " ");
|
||||
else if (inst.name[0] == '$' || inst.name[1] == '$')
|
||||
inst.arg = data;
|
||||
else
|
||||
inst.data = strtol(data, NULL, 10);
|
||||
|
||||
char *duppedname = strdup(inst.name);
|
||||
|
||||
if (!inst.arg)
|
||||
inst.arg = "\n";
|
||||
char *duppedarg = strdup(inst.arg);
|
||||
|
||||
stack->program[stack->program_size++] = (Instruction){duppedname, duppedarg, inst.data};
|
||||
}
|
||||
}
|
35
src/stack.h
Normal file
35
src/stack.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
char *arg;
|
||||
uint16_t data;
|
||||
} Instruction;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Instruction program[PROGRAM_MAXSIZE];
|
||||
uint16_t program_size, program_counter, stacksize;
|
||||
int pointer;
|
||||
int16_t labels[MAX_LABELS];
|
||||
uint16_t memory[];
|
||||
} Stack;
|
||||
|
||||
Stack *program_init(uint16_t stacksize);
|
||||
|
||||
void stack_push(Stack *stack, uint16_t data);
|
||||
|
||||
uint16_t stack_pop(Stack *stack);
|
||||
|
||||
uint16_t stack_peek(Stack *stack);
|
||||
|
||||
void kms(Stack *stack, const char *err);
|
||||
|
||||
void parse_and_process(Stack *stack, FILE *file);
|
||||
|
||||
void repl(Stack *stack);
|
25
tests/calc.lb
Normal file
25
tests/calc.lb
Normal file
@ -0,0 +1,25 @@
|
||||
@ 0
|
||||
scan
|
||||
scan
|
||||
scan
|
||||
|jmp 0
|
||||
|
||||
@ 1
|
||||
add
|
||||
meow
|
||||
quit
|
||||
|
||||
@ 2
|
||||
sub
|
||||
meow
|
||||
quit
|
||||
|
||||
@ 3
|
||||
mul
|
||||
meow
|
||||
quit
|
||||
|
||||
@ 4
|
||||
div
|
||||
meow
|
||||
quit
|
16
tests/helloworld.lb
Normal file
16
tests/helloworld.lb
Normal file
@ -0,0 +1,16 @@
|
||||
PUSH 76 ; L
|
||||
PUTC
|
||||
PUSH 97 ; a
|
||||
PUTC
|
||||
PUSH 98 ; b
|
||||
PUTC
|
||||
PUSH 97 ; a
|
||||
PUTC
|
||||
PUSH 115 ; s
|
||||
PUTC
|
||||
PUSH 104 ; h
|
||||
PUTC
|
||||
PUSH 107 ; k
|
||||
PUTC
|
||||
PUSH 105 ; i
|
||||
PUTC
|
Loading…
Reference in New Issue
Block a user