mirror of
https://github.com/chrim05/nds-console.git
synced 2025-06-18 21:55:34 -04:00
added readme
This commit is contained in:
parent
d54ebd1f71
commit
d91682c3dc
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
build/
|
build/
|
||||||
|
.vscode/
|
||||||
*.elf
|
*.elf
|
||||||
*.nds
|
*.nds
|
10
.vscode/c_cpp_properties.json
vendored
10
.vscode/c_cpp_properties.json
vendored
@ -3,15 +3,15 @@
|
|||||||
{
|
{
|
||||||
"name": "Linux",
|
"name": "Linux",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"/opt/devkitpro/devkitARM/arm-none-eabi/include",
|
"C:/devkitpro/devkitARM/arm-none-eabi/include",
|
||||||
"/opt/devkitpro/libnds/include",
|
"C:/devkitpro/libnds/include",
|
||||||
"${workspaceFolder}/**"
|
"${workspaceFolder}/**"
|
||||||
],
|
],
|
||||||
"defines": [],
|
"defines": ["ARM9"],
|
||||||
"compilerPath": "/usr/bin/gcc",
|
"compilerPath": "C:/devkitPro/devkitARM/bin/arm-none-eabi-g++.exe",
|
||||||
"cStandard": "gnu17",
|
"cStandard": "gnu17",
|
||||||
"cppStandard": "gnu++14",
|
"cppStandard": "gnu++14",
|
||||||
"intelliSenseMode": "linux-gcc-x64"
|
"intelliSenseMode": "windows-gcc-x64"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 4
|
"version": 4
|
||||||
|
61
readme.md
Normal file
61
readme.md
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# why
|
||||||
|
* for fun
|
||||||
|
* having a terminal application on your ds which gets more control over it
|
||||||
|
|
||||||
|
# requirements
|
||||||
|
* devkitpro
|
||||||
|
* make
|
||||||
|
* desmume (optional)
|
||||||
|
|
||||||
|
# how to compile it
|
||||||
|
```
|
||||||
|
clone https://github.com/christallo/nds-console
|
||||||
|
cd nds-console
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
# how to run it
|
||||||
|
* on desmume (for debugging)
|
||||||
|
```
|
||||||
|
make && desmume nds-console.nds
|
||||||
|
```
|
||||||
|
* on physical nintendo ds console (for distrubution)
|
||||||
|
* * `make`
|
||||||
|
* * move `nds-console.nds` to your R4 or your modded sd
|
||||||
|
|
||||||
|
# how to edit it in vscode
|
||||||
|
* create a configuration json file for c/cpp
|
||||||
|
* open `.vscode\c_cpp_properties.json`
|
||||||
|
* write
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Win32", // for windows
|
||||||
|
"name": "Linux", // for linux
|
||||||
|
|
||||||
|
"includePath": [
|
||||||
|
"C:/devkitpro/devkitARM/arm-none-eabi/include", // for windows
|
||||||
|
"/opt/devkitpro/devkitARM/arm-none-eabi/include", // for linux
|
||||||
|
|
||||||
|
"C:/devkitpro/libnds/include", // for windows
|
||||||
|
"/opt/devkitpro/libnds/include", // for linux
|
||||||
|
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
|
||||||
|
"defines": ["ARM9"],
|
||||||
|
|
||||||
|
"compilerPath": "C:/devkitPro/devkitARM/bin/arm-none-eabi-g++.exe", // for windows
|
||||||
|
"compilerPath": "/opt/devkitPro/devkitARM/bin/arm-none-eabi-g++.exe", // for linux
|
||||||
|
|
||||||
|
"cStandard": "gnu17",
|
||||||
|
"cppStandard": "gnu++14",
|
||||||
|
"intelliSenseMode": "windows-gcc-x64", // for windows
|
||||||
|
"intelliSenseMode": "linux-gcc-x64", // for linux
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
|
```
|
||||||
|
* delete the line you don't care with comments about your os
|
@ -1,12 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Compiling for ARM9
|
|
||||||
|
|
||||||
#undef ARM7
|
|
||||||
#undef ARM9
|
|
||||||
|
|
||||||
#define ARM9
|
|
||||||
|
|
||||||
#include <nds.h>
|
#include <nds.h>
|
||||||
#include <nds/arm9/console.h>
|
#include <nds/arm9/console.h>
|
||||||
#include <c++/12.1.0/vector>
|
#include <c++/12.1.0/vector>
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
// Compiling for ARM9
|
|
||||||
|
|
||||||
#undef ARM7
|
|
||||||
#undef ARM9
|
|
||||||
|
|
||||||
#define ARM9
|
|
||||||
|
|
||||||
// Devkitpro headers and ARM9 libc++
|
// Devkitpro headers and ARM9 libc++
|
||||||
|
|
||||||
#include <nds.h>
|
#include <nds.h>
|
||||||
@ -23,7 +16,7 @@ int main()
|
|||||||
// initialize video
|
// initialize video
|
||||||
videoSetMode(MODE_0_2D);
|
videoSetMode(MODE_0_2D);
|
||||||
videoSetModeSub(MODE_0_2D);
|
videoSetModeSub(MODE_0_2D);
|
||||||
|
|
||||||
// initialize vram
|
// initialize vram
|
||||||
vramSetPrimaryBanks(VRAM_A_MAIN_BG, VRAM_B_MAIN_SPRITE, VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE);
|
vramSetPrimaryBanks(VRAM_A_MAIN_BG, VRAM_B_MAIN_SPRITE, VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE);
|
||||||
|
|
||||||
@ -62,6 +55,7 @@ int main()
|
|||||||
case KEY_A: console.returnPrompt(); break;
|
case KEY_A: console.returnPrompt(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printing the prompt
|
||||||
console.flushPromptBuffer(frame, true);
|
console.flushPromptBuffer(frame, true);
|
||||||
swiWaitForVBlank();
|
swiWaitForVBlank();
|
||||||
}
|
}
|
||||||
|
@ -276,4 +276,180 @@ std::string NScript::Parser::escapesToEscaped(std::string s, Position pos)
|
|||||||
t.push_back(s[i]);
|
t.push_back(s[i]);
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
NScript::Node NScript::Evaluator::expectType(Node node, NodeKind type, Position pos)
|
||||||
|
{
|
||||||
|
if (node.kind != type)
|
||||||
|
throw Error({"expected a value with type ", Node::kindToString(type), " (found ", Node::kindToString(node.kind), ")"}, pos);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NScript::Evaluator::expectArgsCount(CallNode call, uint64_t count)
|
||||||
|
{
|
||||||
|
if (call.args.size() != count)
|
||||||
|
throw Error({"expected args ", std::to_string(count), " (found ", std::to_string(call.args.size()), ")"}, call.name.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
NScript::Node NScript::Evaluator::builtinFloor(CallNode call)
|
||||||
|
{
|
||||||
|
expectArgsCount(call, 1);
|
||||||
|
|
||||||
|
// truncating the float value
|
||||||
|
auto expr = expectType(evaluateNode(call.args[0]), NodeKind::Num, call.args[0].pos);
|
||||||
|
expr.value.num = uint64_t(expr.value.num);
|
||||||
|
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
NScript::Node NScript::Evaluator::builtinPrint(CallNode call, Position pos)
|
||||||
|
{
|
||||||
|
// printing all arguments without separation and flushing
|
||||||
|
for (auto arg : call.args)
|
||||||
|
iprintf("%s", arg.toString().c_str());
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
return Node::none(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
NScript::Node NScript::Evaluator::evaluateCallProcess(CallNode call, Position pos)
|
||||||
|
{
|
||||||
|
panic("evaluateCallProcess not implemented yet");
|
||||||
|
return Node::none(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
NScript::Node NScript::Evaluator::evaluateCall(CallNode call, Position pos)
|
||||||
|
{
|
||||||
|
// when the call's name is a string, searches for a process with that filename
|
||||||
|
if (call.name.kind == NodeKind::String)
|
||||||
|
return evaluateCallProcess(call, pos);
|
||||||
|
|
||||||
|
// otherwise searches for a builtin function with that name
|
||||||
|
auto name = std::string(call.name.value.str);
|
||||||
|
|
||||||
|
if (name == "print")
|
||||||
|
return builtinPrint(call, pos);
|
||||||
|
else if (name == "floor")
|
||||||
|
return builtinFloor(call);
|
||||||
|
else
|
||||||
|
throw Error({"unknown builtin function"}, call.name.pos);
|
||||||
|
|
||||||
|
return Node::none(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
NScript::Node NScript::Evaluator::evaluateAssign(AssignNode assign, Position pos)
|
||||||
|
{
|
||||||
|
auto name = std::string(assign.name.value.str);
|
||||||
|
auto expr = evaluateNode(assign.expr);
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < map.size(); i++)
|
||||||
|
if (map[i].key == name)
|
||||||
|
{
|
||||||
|
// the variable is already declared (overwrites old value)
|
||||||
|
map[i].val = expr;
|
||||||
|
return Node::none(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the variable is not declared yet (appends a new definition)
|
||||||
|
map.push_back(KeyPair<std::string, Node>(name, expr));
|
||||||
|
return Node::none(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
NScript::Node NScript::Evaluator::evaluateUna(UnaNode una)
|
||||||
|
{
|
||||||
|
auto term = evaluateNode(una.term);
|
||||||
|
|
||||||
|
// unary can only be applied to numbers
|
||||||
|
if (term.kind != NodeKind::Num)
|
||||||
|
throw Error({"type `", Node::kindToString(term.kind), "` does not support unary `", Node::kindToString(una.op.kind), "`"}, term.pos);
|
||||||
|
|
||||||
|
term.value.num *= una.op.kind == NodeKind::Minus ? -1 : +1;
|
||||||
|
return term;
|
||||||
|
}
|
||||||
|
|
||||||
|
cstring_t NScript::Evaluator::evaluateOperationStr(Node op, cstring_t l, cstring_t r)
|
||||||
|
{
|
||||||
|
// string only supports `+` op
|
||||||
|
if (op.kind != NodeKind::Plus)
|
||||||
|
throw Error({"string does not support bin `", Node::kindToString(op.kind), "`"}, op.pos);
|
||||||
|
|
||||||
|
return cstringRealloc((std::string(l) + r).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
float64 NScript::Evaluator::evaluateOperationNum(NodeKind op, float64 l, float64 r, Position rPos)
|
||||||
|
{
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case NodeKind::Plus: return l + r;
|
||||||
|
case NodeKind::Minus: return l - r;
|
||||||
|
case NodeKind::Star: return l * r;
|
||||||
|
case NodeKind::Slash:
|
||||||
|
if (r == 0)
|
||||||
|
throw Error({"dividing by 0"}, rPos);
|
||||||
|
|
||||||
|
return l / r;
|
||||||
|
|
||||||
|
default: panic("unreachable"); return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NScript::Node NScript::Evaluator::evaluateBin(BinNode bin)
|
||||||
|
{
|
||||||
|
auto left = evaluateNode(bin.left);
|
||||||
|
auto right = evaluateNode(bin.right);
|
||||||
|
|
||||||
|
// every bin op can only be applied to values of same type
|
||||||
|
if (left.kind != right.kind)
|
||||||
|
throw Error(
|
||||||
|
{"unkwnon bin `", bin.op.toString(), "` between different types (`", Node::kindToString(left.kind), "` and `", Node::kindToString(right.kind), "`)"},
|
||||||
|
bin.op.pos
|
||||||
|
);
|
||||||
|
|
||||||
|
// recognizing the values' types
|
||||||
|
switch (left.kind)
|
||||||
|
{
|
||||||
|
case NodeKind::Num:
|
||||||
|
left.value.num = evaluateOperationNum(bin.op.kind, left.value.num, right.value.num, right.pos);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NodeKind::String:
|
||||||
|
left.value.str = evaluateOperationStr(bin.op, left.value.str, right.value.str);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw Error(
|
||||||
|
{"type `", Node::kindToString(left.kind), "` does not support bin"},
|
||||||
|
bin.op.pos
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the returning value is gonna have the same pos of the entire bin node
|
||||||
|
left.pos.endPos = right.pos.endPos;
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
NScript::Node NScript::Evaluator::evaluateIdentifier(Node identifier)
|
||||||
|
{
|
||||||
|
for (const auto& kv : map)
|
||||||
|
if (kv.key == std::string(identifier.value.str))
|
||||||
|
return kv.val;
|
||||||
|
|
||||||
|
throw Error({"unknown variable"}, identifier.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
NScript::Node NScript::Evaluator::evaluateNode(Node node)
|
||||||
|
{
|
||||||
|
switch (node.kind)
|
||||||
|
{
|
||||||
|
case NodeKind::Num:
|
||||||
|
case NodeKind::String:
|
||||||
|
case NodeKind::None: return node;
|
||||||
|
case NodeKind::Bin: return evaluateBin(*node.value.bin);
|
||||||
|
case NodeKind::Una: return evaluateUna(*node.value.una);
|
||||||
|
case NodeKind::Identifier: return evaluateIdentifier(node);
|
||||||
|
case NodeKind::Assign: return evaluateAssign(*node.value.assign, node.pos);
|
||||||
|
case NodeKind::Call: return evaluateCall(*node.value.call, node.pos);
|
||||||
|
default: panic("unimplemented evaluateNode for some NodeKind"); return Node::none(node.pos);
|
||||||
|
}
|
||||||
}
|
}
|
179
source/nscript.h
179
source/nscript.h
@ -1,12 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Compiling for ARM9
|
|
||||||
|
|
||||||
#undef ARM7
|
|
||||||
#undef ARM9
|
|
||||||
|
|
||||||
#define ARM9
|
|
||||||
|
|
||||||
#include <nds.h>
|
#include <nds.h>
|
||||||
#include <c++/12.1.0/string>
|
#include <c++/12.1.0/string>
|
||||||
#include <c++/12.1.0/vector>
|
#include <c++/12.1.0/vector>
|
||||||
@ -405,176 +398,30 @@ namespace NScript
|
|||||||
this->map = std::vector<KeyPair<std::string, Node>>();
|
this->map = std::vector<KeyPair<std::string, Node>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public: Node evaluateNode(Node node)
|
public: Node evaluateNode(Node node);
|
||||||
{
|
|
||||||
switch (node.kind)
|
|
||||||
{
|
|
||||||
case NodeKind::Num:
|
|
||||||
case NodeKind::String:
|
|
||||||
case NodeKind::None: return node;
|
|
||||||
case NodeKind::Bin: return evaluateBin(*node.value.bin);
|
|
||||||
case NodeKind::Una: return evaluateUna(*node.value.una);
|
|
||||||
case NodeKind::Identifier: return evaluateIdentifier(node);
|
|
||||||
case NodeKind::Assign: return evaluateAssign(*node.value.assign, node.pos);
|
|
||||||
case NodeKind::Call: return evaluateCall(*node.value.call, node.pos);
|
|
||||||
default: panic("unimplemented evaluateNode for some NodeKind"); return Node::none(node.pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private: Node evaluateIdentifier(Node identifier)
|
private: Node evaluateIdentifier(Node identifier);
|
||||||
{
|
|
||||||
for (const auto& kv : map)
|
|
||||||
if (kv.key == std::string(identifier.value.str))
|
|
||||||
return kv.val;
|
|
||||||
|
|
||||||
throw Error({"unknown variable"}, identifier.pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private: Node evaluateBin(BinNode bin)
|
private: Node evaluateBin(BinNode bin);
|
||||||
{
|
|
||||||
auto left = evaluateNode(bin.left);
|
|
||||||
auto right = evaluateNode(bin.right);
|
|
||||||
|
|
||||||
if (left.kind != right.kind)
|
private: float64 evaluateOperationNum(NodeKind op, float64 l, float64 r, Position rPos);
|
||||||
throw Error(
|
|
||||||
{"unkwnon bin `", bin.op.toString(), "` between different types (`", Node::kindToString(left.kind), "` and `", Node::kindToString(right.kind), "`)"},
|
|
||||||
bin.op.pos
|
|
||||||
);
|
|
||||||
|
|
||||||
switch (left.kind)
|
|
||||||
{
|
|
||||||
case NodeKind::Num:
|
|
||||||
left.value.num = evaluateOperationNum(bin.op.kind, left.value.num, right.value.num, right.pos);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NodeKind::String:
|
|
||||||
left.value.str = evaluateOperationStr(bin.op, left.value.str, right.value.str);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
private: cstring_t evaluateOperationStr(Node op, cstring_t l, cstring_t r);
|
||||||
throw Error(
|
|
||||||
{"type `", Node::kindToString(left.kind), "` does not support bin"},
|
|
||||||
bin.op.pos
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
left.pos.endPos = right.pos.endPos;
|
private: Node evaluateUna(UnaNode una);
|
||||||
return left;
|
|
||||||
}
|
|
||||||
|
|
||||||
private: float64 evaluateOperationNum(NodeKind op, float64 l, float64 r, Position rPos)
|
private: Node evaluateAssign(AssignNode assign, Position pos);
|
||||||
{
|
|
||||||
switch (op)
|
|
||||||
{
|
|
||||||
case NodeKind::Plus: return l + r;
|
|
||||||
case NodeKind::Minus: return l - r;
|
|
||||||
case NodeKind::Star: return l * r;
|
|
||||||
case NodeKind::Slash:
|
|
||||||
if (r == 0)
|
|
||||||
throw Error({"dividing by 0"}, rPos);
|
|
||||||
|
|
||||||
return l / r;
|
private: Node evaluateCall(CallNode call, Position pos);
|
||||||
|
|
||||||
default: panic("unreachable"); return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private: cstring_t evaluateOperationStr(Node op, cstring_t l, cstring_t r)
|
private: Node evaluateCallProcess(CallNode call, Position pos);
|
||||||
{
|
|
||||||
if (op.kind != NodeKind::Plus)
|
|
||||||
throw Error({"string does not support bin `", Node::kindToString(op.kind), "`"}, op.pos);
|
|
||||||
|
|
||||||
return cstringRealloc((std::string(l) + r).c_str());
|
private: Node builtinPrint(CallNode call, Position pos);
|
||||||
}
|
|
||||||
|
|
||||||
private: Node evaluateUna(UnaNode una)
|
private: Node builtinFloor(CallNode call);
|
||||||
{
|
|
||||||
auto term = evaluateNode(una.term);
|
|
||||||
|
|
||||||
if (term.kind != NodeKind::Num)
|
private: void expectArgsCount(CallNode call, uint64_t count);
|
||||||
throw Error({"type `", Node::kindToString(term.kind), "` does not support unary `", Node::kindToString(una.op.kind), "`"}, term.pos);
|
|
||||||
|
|
||||||
term.value.num *= una.op.kind == NodeKind::Minus ? -1 : +1;
|
|
||||||
return term;
|
|
||||||
}
|
|
||||||
|
|
||||||
private: Node evaluateAssign(AssignNode assign, Position pos)
|
private: Node expectType(Node node, NodeKind type, Position pos);
|
||||||
{
|
|
||||||
auto name = std::string(assign.name.value.str);
|
|
||||||
auto expr = evaluateNode(assign.expr);
|
|
||||||
|
|
||||||
for (uint64_t i = 0; i < map.size(); i++)
|
|
||||||
if (map[i].key == name)
|
|
||||||
{
|
|
||||||
// the variable is already declared (overwrites old value)
|
|
||||||
map[i].val = expr;
|
|
||||||
return Node::none(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the variable is not declared yet (appends a new definition)
|
|
||||||
map.push_back(KeyPair<std::string, Node>(name, expr));
|
|
||||||
return Node::none(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private: Node evaluateCall(CallNode call, Position pos)
|
|
||||||
{
|
|
||||||
// when the call's name is a string, searches for a process with that filename
|
|
||||||
if (call.name.kind == NodeKind::String)
|
|
||||||
return evaluateCallProcess(call, pos);
|
|
||||||
|
|
||||||
// otherwise searches for a builtin function with that name
|
|
||||||
|
|
||||||
auto name = std::string(call.name.value.str);
|
|
||||||
|
|
||||||
if (name == "print")
|
|
||||||
return builtinPrint(call, pos);
|
|
||||||
else if (name == "floor")
|
|
||||||
return builtinFloor(call);
|
|
||||||
else
|
|
||||||
throw Error({"unknown builtin function"}, call.name.pos);
|
|
||||||
|
|
||||||
return Node::none(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private: Node evaluateCallProcess(CallNode call, Position pos)
|
|
||||||
{
|
|
||||||
panic("evaluateCallProcess not implemented yet");
|
|
||||||
return Node::none(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private: Node builtinPrint(CallNode call, Position pos)
|
|
||||||
{
|
|
||||||
// printing all arguments without separation and flushing
|
|
||||||
for (auto arg : call.args)
|
|
||||||
iprintf("%s", arg.toString().c_str());
|
|
||||||
|
|
||||||
fflush(stdout);
|
|
||||||
return Node::none(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private: Node builtinFloor(CallNode call)
|
|
||||||
{
|
|
||||||
expectArgsCount(call, 1);
|
|
||||||
|
|
||||||
// truncating the float value
|
|
||||||
auto expr = expectType(evaluateNode(call.args[0]), NodeKind::Num, call.args[0].pos);
|
|
||||||
expr.value.num = uint64_t(expr.value.num);
|
|
||||||
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private: void expectArgsCount(CallNode call, uint64_t count)
|
|
||||||
{
|
|
||||||
if (call.args.size() != count)
|
|
||||||
throw Error({"expected args ", std::to_string(count), " (found ", std::to_string(call.args.size()), ")"}, call.name.pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private: Node expectType(Node node, NodeKind type, Position pos)
|
|
||||||
{
|
|
||||||
if (node.kind != type)
|
|
||||||
throw Error({"expected a value with type ", Node::kindToString(type), " (found ", Node::kindToString(node.kind), ")"}, pos);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user