Compare commits

...

2 Commits

Author SHA1 Message Date
2ae3086481 Vim fix, lists and strings size fix 2025-10-06 18:33:12 +11:00
38557cdf4c more fixes 2025-10-06 18:25:12 +11:00
4 changed files with 73 additions and 18 deletions

52
.vim/indent/kyn.vim Normal file
View 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

View File

@@ -39,7 +39,7 @@ Value handleListGet(const Value& subject, const std::vector<Value>& args) {
return Value(); return Value();
} }
Value accessor = args[0]; 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()); return Value((long long)subject.list.size());
} }
if (accessor.valtype != ValueType::Int) { if (accessor.valtype != ValueType::Int) {

View File

@@ -39,7 +39,7 @@ Value handleStringGet(const Value& subject, const std::vector<Value>& args) {
} }
Value accessor = args[0]; Value accessor = args[0];
if (accessor.valtype != ValueType::Int) { 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()); return Value((long long)subject.string_val.length());
} }
error("String accessor must be an integer or \"size\""); error("String accessor must be an integer or \"size\"");

View File

@@ -45,11 +45,7 @@ Value execute(Instruction inst) {
return modules::assert(inst.args); return modules::assert(inst.args);
} }
// For all other instructions, evaluate the arguments first // Handle variable operations that require unevaluated arguments
for(auto& arg : inst.args) {
arg = evaluate(arg);
}
if (inst.instruction == InstructionType::Variable) { if (inst.instruction == InstructionType::Variable) {
auto& args = inst.args; auto& args = inst.args;
@@ -123,8 +119,6 @@ Value execute(Instruction inst) {
return instance; return instance;
} }
// Indexed assignment: $var index = value // Indexed assignment: $var index = value
if (args.size() == 4 && args[2].valtype == ValueType::Identifier && args[2].string_val == "=") { if (args.size() == 4 && args[2].valtype == ValueType::Identifier && args[2].string_val == "=") {
std::string var_name; std::string var_name;
@@ -172,14 +166,23 @@ Value execute(Instruction inst) {
data::modifyValue(var_name, new_val); data::modifyValue(var_name, new_val);
return Value(); return Value();
} }
}
// Variable access or indexed get // For all other instructions, evaluate the arguments first
// If args[0] is an Identifier and there are no args, it's a variable access. for(auto& arg : inst.args) {
if (args[0].valtype == ValueType::Identifier && args.empty()) { arg = evaluate(arg);
return data::getValue(args[0].string_val); }
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()); std::vector<Value> op_args(args.begin() + 1, args.end());
if (op_args.empty()) { if (op_args.empty()) {
@@ -189,14 +192,14 @@ Value execute(Instruction inst) {
// Indexed get: subject index // Indexed get: subject index
if (subject.valtype == ValueType::List) { if (subject.valtype == ValueType::List) {
return handleListGet(subject, op_args); return handleListGet(subject, op_args);
} else if (subject.valtype == ValueType::String) { } else if (subject.valtype == ValueType::String) {
return handleStringGet(subject, op_args); return handleStringGet(subject, op_args);
} else if (subject.valtype == ValueType::Map) { } else if (subject.valtype == ValueType::Map) {
if (op_args.empty()) { if (op_args.empty()) {
return subject; return subject;
} }
if (op_args[0].valtype != ValueType::Identifier) { if (op_args[0].valtype != ValueType::Identifier && op_args[0].valtype != ValueType::String) {
error("Struct member name must be an identifier."); error("Struct member name must be an identifier or string.");
return Value(); return Value();
} }
std::string member_name = op_args[0].string_val; std::string member_name = op_args[0].string_val;
@@ -218,7 +221,7 @@ Value execute(Instruction inst) {
data::pushScope(); data::pushScope();
data::scopes.back()["self"] = subject; data::scopes.back()["self"] = subject;
for (size_t i = 0; i < func.arg_names.size(); ++i) { 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; Value return_val;
for (const auto& body_inst : func.body) { for (const auto& body_inst : func.body) {