Fixes and functions
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
enum class InstructionType {
|
||||
None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare
|
||||
None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function
|
||||
};
|
||||
|
||||
enum class ValueType {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "../modules/while/while.h"
|
||||
#include "../modules/compare/compare.h"
|
||||
#include "../modules/input/input.h"
|
||||
#include "../modules/function/function.h"
|
||||
|
||||
Value execute(Instruction inst) {
|
||||
// Special cases that need to manage their own argument evaluation
|
||||
@@ -24,6 +25,9 @@ Value execute(Instruction inst) {
|
||||
if (inst.instruction == InstructionType::While) {
|
||||
return modules::whiles(inst.args);
|
||||
}
|
||||
if (inst.instruction == InstructionType::Function) {
|
||||
return modules::fndef(inst.args);
|
||||
}
|
||||
|
||||
// For all other instructions, evaluate the arguments first
|
||||
size_t i = 0;
|
||||
@@ -64,7 +68,17 @@ Value execute(Instruction inst) {
|
||||
case InstructionType::Exit:
|
||||
return modules::exit(inst.args);
|
||||
break;
|
||||
case InstructionType::Variable:
|
||||
case InstructionType::Variable: {
|
||||
if (!inst.args.empty()) {
|
||||
const std::string& name = inst.args[0].real;
|
||||
if (data::functions.count(name)) {
|
||||
Value return_val;
|
||||
for (const auto& body_inst : data::functions.at(name)) {
|
||||
return_val = execute(body_inst);
|
||||
}
|
||||
return return_val;
|
||||
}
|
||||
}
|
||||
if (inst.args.size() > 2 && inst.args[1].valtype == ValueType::Real && inst.args[1].real == "=") {
|
||||
return varmod(inst.args);
|
||||
} else {
|
||||
@@ -72,6 +86,7 @@ Value execute(Instruction inst) {
|
||||
return Value("");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Note: 'If' and 'Let' are already handled.
|
||||
error("Unknown instruction");
|
||||
|
||||
@@ -7,8 +7,8 @@ int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
repl();
|
||||
} else {
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-h") || strcmp(argv[i], "--help")) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
|
||||
std::cout << "Kyn programming language" << std::endl;
|
||||
std::cout << "Usage: " << argv[0] << " (filename).kyn" << std::endl;
|
||||
std::cout << "Kyn is licensed to you under the Mozilla Public License v2.0" << std::endl;
|
||||
@@ -16,7 +16,6 @@ int main(int argc, char** argv) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
execFile(argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
25
src/modules/function/function.cpp
Normal file
25
src/modules/function/function.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "function.h"
|
||||
#include "../../defs/defs.h"
|
||||
#include "../../data/data.h"
|
||||
#include "../../error/error.h"
|
||||
#include <vector>
|
||||
|
||||
Value modules::fndef(std::vector<Value> args) {
|
||||
if (args.size() < 2) {
|
||||
error("Syntax error: function statement requires a name and a body");
|
||||
return Value();
|
||||
}
|
||||
if (args[0].valtype != ValueType::Processed) {
|
||||
error("Syntax error: function name must be a processed value");
|
||||
return Value();
|
||||
}
|
||||
if (args[1].valtype != ValueType::InstructionGroup) {
|
||||
error("Syntax error: function body must be an instruction group");
|
||||
return Value();
|
||||
}
|
||||
|
||||
std::string func_name = args[0].processed->args[0].real;
|
||||
data::functions[func_name] = args[1].instructionGroup;
|
||||
|
||||
return Value("");
|
||||
}
|
||||
8
src/modules/function/function.h
Normal file
8
src/modules/function/function.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../defs/defs.h"
|
||||
#include <vector>
|
||||
|
||||
namespace modules {
|
||||
Value fndef(std::vector<Value> args);
|
||||
}
|
||||
@@ -137,9 +137,42 @@ std::vector<Instruction> parse(std::string program) {
|
||||
std::string then_content = line.substr(block_start + 1, block_end - block_start - 1);
|
||||
while_inst.args.push_back(Value(parse(then_content))); // Recursive call
|
||||
instructions.push_back(while_inst);
|
||||
} else if (line.rfind("fun", 0) == 0) {
|
||||
Instruction function_inst;
|
||||
function_inst.instruction = InstructionType::Function;
|
||||
|
||||
size_t block_start = line.find('{');
|
||||
if (block_start == std::string::npos) {
|
||||
error("Expected '{' for function statement");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1. Function name
|
||||
std::string name = line.substr(3, block_start - 3);
|
||||
function_inst.args.push_back(Value(Instruction(split(trim(name)))));
|
||||
|
||||
// 2. Find 'then' block
|
||||
size_t block_end = 0;
|
||||
int brace_level = 0;
|
||||
for (size_t i = block_start; i < line.length(); ++i) {
|
||||
if (line[i] == '{') brace_level++;
|
||||
else if (line[i] == '}') brace_level--;
|
||||
if (brace_level == 0) {
|
||||
block_end = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (block_end == 0) {
|
||||
error("Mismatched braces in function statement");
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string then_content = line.substr(block_start + 1, block_end - block_start - 1);
|
||||
function_inst.args.push_back(Value(parse(then_content))); // Recursive call
|
||||
instructions.push_back(function_inst);
|
||||
} else {
|
||||
instructions.push_back(Instruction(split(line)));
|
||||
}
|
||||
}
|
||||
return instructions;
|
||||
}
|
||||
}
|
||||
|
||||
5
tests/func.kyn
Normal file
5
tests/func.kyn
Normal file
@@ -0,0 +1,5 @@
|
||||
fun dingus {
|
||||
println "hello"
|
||||
}
|
||||
|
||||
dingus
|
||||
6
tests/loop.kyn
Normal file
6
tests/loop.kyn
Normal file
@@ -0,0 +1,6 @@
|
||||
let counter = 0
|
||||
|
||||
while compare $counter <= 1000 {
|
||||
println $counter
|
||||
counter = (math 1 + $counter)
|
||||
}
|
||||
Reference in New Issue
Block a user