Compare commits
6 Commits
8fea13cc17
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| d85efb69dc | |||
| a6c3a0e39e | |||
| e4432cbe21 | |||
| 26cb591c49 | |||
| 2ae3086481 | |||
| 38557cdf4c |
52
.vim/indent/kyn.vim
Normal file
52
.vim/indent/kyn.vim
Normal file
@@ -0,0 +1,52 @@
|
||||
" Vim indent file
|
||||
" Language: Kyn
|
||||
" Maintainer: Gemini
|
||||
|
||||
if exists("b:did_indent")
|
||||
finish
|
||||
endif
|
||||
let b:did_indent = 1
|
||||
|
||||
setlocal indentexpr=GetKynIndent()
|
||||
setlocal indentkeys+=={,},0)
|
||||
|
||||
let b:undo_indent = "setlocal indentexpr< indentkeys<"
|
||||
|
||||
" Only define the function once
|
||||
if exists("*GetKynIndent")
|
||||
finish
|
||||
endif
|
||||
|
||||
function GetKynIndent()
|
||||
" Get the line number of the current line
|
||||
let lnum = v:lnum
|
||||
|
||||
" Get the current line
|
||||
let cline = getline(lnum)
|
||||
|
||||
" If the current line has a '}', decrease indent
|
||||
if cline =~ '^\s*}'
|
||||
let lnum = prevnonblank(lnum - 1)
|
||||
return indent(lnum)
|
||||
endif
|
||||
|
||||
" Find the previous non-blank line
|
||||
let lnum = prevnonblank(lnum - 1)
|
||||
|
||||
" At the start of the file, no indent
|
||||
if lnum == 0
|
||||
return 0
|
||||
endif
|
||||
|
||||
" Get the indent of the previous line
|
||||
let prev_indent = indent(lnum)
|
||||
let prev_line = getline(lnum)
|
||||
|
||||
" If the previous line ends with '{', increase indent
|
||||
if prev_line =~ '{\s*$'
|
||||
return prev_indent + &shiftwidth
|
||||
endif
|
||||
|
||||
" Otherwise, keep the same indent
|
||||
return prev_indent
|
||||
endfunction
|
||||
@@ -39,7 +39,7 @@ Value handleListGet(const Value& subject, const std::vector<Value>& args) {
|
||||
return Value();
|
||||
}
|
||||
Value accessor = args[0];
|
||||
if (accessor.valtype == ValueType::String && accessor.string_val == "size") {
|
||||
if (accessor.valtype == ValueType::Identifier && accessor.string_val == "size") {
|
||||
return Value((long long)subject.list.size());
|
||||
}
|
||||
if (accessor.valtype != ValueType::Int) {
|
||||
|
||||
@@ -39,7 +39,7 @@ Value handleStringGet(const Value& subject, const std::vector<Value>& args) {
|
||||
}
|
||||
Value accessor = args[0];
|
||||
if (accessor.valtype != ValueType::Int) {
|
||||
if (accessor.valtype == ValueType::String && accessor.string_val == "size") {
|
||||
if (accessor.valtype == ValueType::Identifier && accessor.string_val == "size") {
|
||||
return Value((long long)subject.string_val.length());
|
||||
}
|
||||
error("String accessor must be an integer or \"size\"");
|
||||
@@ -51,7 +51,7 @@ Value handleStringGet(const Value& subject, const std::vector<Value>& args) {
|
||||
error("String index out of bounds");
|
||||
return Value();
|
||||
}
|
||||
return Value(std::string(1, subject.string_val.at(index)));
|
||||
return Value("\"" + std::string(1, subject.string_val.at(index)) + "\"");
|
||||
}
|
||||
|
||||
void handleStringSet(std::string var_name, Value& subject, const Value& index_val, const Value& new_val) {
|
||||
|
||||
@@ -77,18 +77,18 @@ Instruction::Instruction(std::vector<Value> toks) {
|
||||
|
||||
Value::Value(std::string stringval) {
|
||||
// This constructor will attempt to parse the string into the most specific type possible.
|
||||
if (stringval.length() > 2 && stringval.front() == '<' && stringval.back() == '>') {
|
||||
valtype = ValueType::TypePlaceholder;
|
||||
type_placeholder_name = stringval.substr(1, stringval.length() - 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stringval.length() >= 2 && stringval.front() == '"' && stringval.back() == '"') {
|
||||
valtype = ValueType::String;
|
||||
string_val = interpretEscapeSequences(stringval.substr(1, stringval.length() - 2));
|
||||
return;
|
||||
}
|
||||
|
||||
if (stringval.length() > 2 && stringval.front() == '<' && stringval.back() == '>') {
|
||||
valtype = ValueType::TypePlaceholder;
|
||||
type_placeholder_name = stringval.substr(1, stringval.length() - 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stringval.empty()) {
|
||||
valtype = ValueType::None;
|
||||
string_val = "";
|
||||
@@ -274,7 +274,7 @@ std::vector<Value> split(std::string line) {
|
||||
splitvals.push_back(Value(buf));
|
||||
}
|
||||
buf = "";
|
||||
} else if (chr == '(' || chr == '[') {
|
||||
} else if ((chr == '(' || chr == '[') && !instring) {
|
||||
if (brackets == 0) {
|
||||
bracket_type = chr;
|
||||
if (!buf.empty()) {
|
||||
@@ -285,7 +285,7 @@ std::vector<Value> split(std::string line) {
|
||||
buf += chr;
|
||||
}
|
||||
brackets++;
|
||||
} else if (chr == ')' || chr == ']') {
|
||||
} else if ((chr == ')' || chr == ']') && !instring) {
|
||||
brackets--;
|
||||
if (brackets == 0) {
|
||||
if (!buf.empty()) {
|
||||
|
||||
@@ -67,6 +67,7 @@ struct Instruction {
|
||||
InstructionType instruction = InstructionType::None;
|
||||
std::vector<Value> args;
|
||||
std::string toString() const;
|
||||
int lineNum;
|
||||
Instruction() = default;
|
||||
Instruction(std::vector<std::string> toks);
|
||||
Instruction(std::vector<Value> toks);
|
||||
|
||||
@@ -45,11 +45,7 @@ Value execute(Instruction inst) {
|
||||
return modules::assert(inst.args);
|
||||
}
|
||||
|
||||
// For all other instructions, evaluate the arguments first
|
||||
for(auto& arg : inst.args) {
|
||||
arg = evaluate(arg);
|
||||
}
|
||||
|
||||
// Handle variable operations that require unevaluated arguments
|
||||
if (inst.instruction == InstructionType::Variable) {
|
||||
auto& args = inst.args;
|
||||
|
||||
@@ -123,8 +119,6 @@ Value execute(Instruction inst) {
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Indexed assignment: $var index = value
|
||||
if (args.size() == 4 && args[2].valtype == ValueType::Identifier && args[2].string_val == "=") {
|
||||
std::string var_name;
|
||||
@@ -172,14 +166,23 @@ Value execute(Instruction inst) {
|
||||
data::modifyValue(var_name, new_val);
|
||||
return Value();
|
||||
}
|
||||
}
|
||||
|
||||
// Variable access or indexed get
|
||||
// If args[0] is an Identifier and there are no args, it's a variable access.
|
||||
if (args[0].valtype == ValueType::Identifier && args.empty()) {
|
||||
return data::getValue(args[0].string_val);
|
||||
// For all other instructions, evaluate the arguments first
|
||||
for(auto& arg : inst.args) {
|
||||
arg = evaluate(arg);
|
||||
}
|
||||
|
||||
if (inst.instruction == InstructionType::Variable) {
|
||||
// This part handles variable access and member/method access on evaluated arguments
|
||||
auto& args = inst.args;
|
||||
|
||||
if (args.empty()) {
|
||||
error("Empty variable instruction after evaluation");
|
||||
return Value();
|
||||
}
|
||||
|
||||
Value subject = evaluate(args[0]);
|
||||
Value subject = args[0]; // First arg is already evaluated
|
||||
std::vector<Value> op_args(args.begin() + 1, args.end());
|
||||
|
||||
if (op_args.empty()) {
|
||||
@@ -189,14 +192,14 @@ Value execute(Instruction inst) {
|
||||
// Indexed get: subject index
|
||||
if (subject.valtype == ValueType::List) {
|
||||
return handleListGet(subject, op_args);
|
||||
} else if (subject.valtype == ValueType::String) {
|
||||
} else if (subject.valtype == ValueType::String) {
|
||||
return handleStringGet(subject, op_args);
|
||||
} else if (subject.valtype == ValueType::Map) {
|
||||
if (op_args.empty()) {
|
||||
return subject;
|
||||
}
|
||||
if (op_args[0].valtype != ValueType::Identifier) {
|
||||
error("Struct member name must be an identifier.");
|
||||
if (op_args[0].valtype != ValueType::Identifier && op_args[0].valtype != ValueType::String) {
|
||||
error("Struct member name must be an identifier or string.");
|
||||
return Value();
|
||||
}
|
||||
std::string member_name = op_args[0].string_val;
|
||||
@@ -218,7 +221,7 @@ Value execute(Instruction inst) {
|
||||
data::pushScope();
|
||||
data::scopes.back()["self"] = subject;
|
||||
for (size_t i = 0; i < func.arg_names.size(); ++i) {
|
||||
data::scopes.back()[func.arg_names[i]] = evaluate(func_args[i]);
|
||||
data::scopes.back()[func.arg_names[i]] = func_args[i];
|
||||
}
|
||||
Value return_val;
|
||||
for (const auto& body_inst : func.body) {
|
||||
|
||||
@@ -7,6 +7,7 @@ Value modules::concat(std::vector<Value> args) {
|
||||
std::string buf;
|
||||
for (Value val : args) {
|
||||
switch (val.valtype) {
|
||||
case ValueType::Identifier:
|
||||
case ValueType::String:
|
||||
buf += val.string_val;
|
||||
break;
|
||||
@@ -17,7 +18,7 @@ Value modules::concat(std::vector<Value> args) {
|
||||
buf += std::to_string(val.double_val);
|
||||
break;
|
||||
default:
|
||||
error("Can only concatenate String, Int, and Double values");
|
||||
error("Can only concatenate String, Int, and Double values. Value given: " + val.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,45 @@
|
||||
#include "split.h"
|
||||
#include "../../defs/defs.h"
|
||||
#include "../../error/error.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
Value modules::split(std::vector<Value> args) {
|
||||
return Value("Work in progress!");
|
||||
if (args.size() < 1) {
|
||||
error("Not enough args for split module");
|
||||
}
|
||||
if (args[0].valtype != ValueType::String) {
|
||||
error("First argument of split must be a string");
|
||||
}
|
||||
std::string delimiter = " ";
|
||||
if (args.size() > 1) {
|
||||
if (args[1].valtype == ValueType::String) {
|
||||
delimiter = args[1].string_val;
|
||||
} else {
|
||||
error("Expected a string delimiter as second argument of split");
|
||||
}
|
||||
}
|
||||
|
||||
std::string buf;
|
||||
std::vector<Value> list;
|
||||
|
||||
for (const char& chr : args[0].string_val) {
|
||||
buf += chr;
|
||||
|
||||
if (buf.size() >= delimiter.size()) {
|
||||
std::string checker = buf.substr(buf.size() - delimiter.size());
|
||||
|
||||
if (checker == delimiter) {
|
||||
list.push_back(Value("\"" + buf.substr(0, buf.size() - delimiter.size()) + "\""));
|
||||
buf.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!buf.empty()) {
|
||||
list.push_back(Value("\"" + buf + "\""));
|
||||
}
|
||||
|
||||
|
||||
return Value(list);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ std::vector<Instruction> parse(std::string program) {
|
||||
std::vector<std::string> lines;
|
||||
std::string buf;
|
||||
int blockTracker = 0;
|
||||
int lineNum = 0;
|
||||
|
||||
for (char chr : program) {
|
||||
if (chr == '\n') lineNum ++;
|
||||
if (chr == '{') {
|
||||
blockTracker++;
|
||||
} else if (chr == '}') {
|
||||
@@ -23,7 +25,7 @@ std::vector<Instruction> parse(std::string program) {
|
||||
|
||||
if ((chr == '\n' || chr == ';') && blockTracker == 0) {
|
||||
if (!buf.empty()) {
|
||||
lines.push_back(buf);
|
||||
lines.push_back(trim(buf));
|
||||
buf.clear();
|
||||
}
|
||||
} else {
|
||||
@@ -90,9 +92,18 @@ std::vector<Instruction> parse(std::string program) {
|
||||
error("Expected '{' for else statement");
|
||||
continue;
|
||||
}
|
||||
size_t else_block_end = remaining_line.find_last_of('}');
|
||||
if (else_block_end == std::string::npos) {
|
||||
error("Expected '}' for else statement");
|
||||
size_t else_block_end = 0;
|
||||
int brace_level = 0;
|
||||
for (size_t i = else_block_start; i < remaining_line.length(); ++i) {
|
||||
if (remaining_line[i] == '{') brace_level++;
|
||||
else if (remaining_line[i] == '}') brace_level--;
|
||||
if (brace_level == 0) {
|
||||
else_block_end = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (else_block_end == 0) {
|
||||
error("Mismatched braces in else statement");
|
||||
continue;
|
||||
}
|
||||
std::string else_content = remaining_line.substr(else_block_start + 1, else_block_end - else_block_start - 1);
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
// Helper to trim whitespace from the start and end of a string
|
||||
std::string trim(const std::string& str) {
|
||||
size_t first = str.find_first_not_of(" \t\n\r");
|
||||
size_t first = str.find_first_not_of(" \t\n");
|
||||
if (std::string::npos == first) {
|
||||
return str;
|
||||
return "";
|
||||
}
|
||||
size_t last = str.find_last_not_of(" \t\n\r");
|
||||
size_t last = str.find_last_not_of(" \t\n");
|
||||
return str.substr(first, (last - first + 1));
|
||||
}
|
||||
|
||||
|
||||
47
tests/toInt.kyn
Normal file
47
tests/toInt.kyn
Normal file
@@ -0,0 +1,47 @@
|
||||
fun toInt in {
|
||||
assert $in is <String>
|
||||
let retint = 0
|
||||
let counter = 0
|
||||
let power = ($in size)
|
||||
let size = ($in size)
|
||||
while compare $counter < $size {
|
||||
let char = ($in $counter)
|
||||
power = (math $power - 1)
|
||||
if compare $char == "1" {
|
||||
retint = (math $retint + (math 1 * 10 ^ $power))
|
||||
}
|
||||
if compare $char == "2" {
|
||||
retint = (math $retint + (math 2 * 10 ^ $power))
|
||||
}
|
||||
if compare $char == "3" {
|
||||
retint = (math $retint + (math 3 * 10 ^ $power))
|
||||
}
|
||||
if compare $char == "4" {
|
||||
retint = (math $retint + (math 4 * 10 ^ $power))
|
||||
}
|
||||
if compare $char == "5" {
|
||||
retint = (math $retint + (math 5 * 10 ^ $power))
|
||||
}
|
||||
if compare $char == "6" {
|
||||
retint = (math $retint + (math 6 * 10 ^ $power))
|
||||
}
|
||||
if compare $char == "7" {
|
||||
retint = (math $retint + (math 7 * 10 ^ $power))
|
||||
}
|
||||
if compare $char == "8" {
|
||||
retint = (math $retint + (math 8 * 10 ^ $power))
|
||||
}
|
||||
if compare $char == "9" {
|
||||
retint = (math $retint + (math 9 * 10 ^ $power))
|
||||
}
|
||||
if compare $char == "0" {
|
||||
# whole lotta nothing
|
||||
}
|
||||
counter = (math $counter + 1)
|
||||
|
||||
}
|
||||
return $retint
|
||||
}
|
||||
let myInt = (toInt "4738927643289")
|
||||
|
||||
println $myInt
|
||||
Reference in New Issue
Block a user