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