Skip to content

Commit ba17d59

Browse files
author
jon
committed
(printf)
1 parent 3cd3c01 commit ba17d59

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

jo_clojure.cpp

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3049,6 +3049,85 @@ static node_idx_t native_prn_str(env_ptr_t env, list_ptr_t args) {
30493049
return new_node_string(s);
30503050
}
30513051

3052+
static node_idx_t native_printf(env_ptr_t env, list_ptr_t args) {
3053+
list_t::iterator it(args);
3054+
if (!it) {
3055+
warnf("printf requires at least a format string argument\n");
3056+
return NIL_NODE;
3057+
}
3058+
3059+
// Get format string
3060+
node_t* format_node = get_node(*it);
3061+
if (format_node->type != NODE_STRING) {
3062+
warnf("printf first argument must be a string\n");
3063+
return NIL_NODE;
3064+
}
3065+
3066+
jo_string format_str = format_node->t_string;
3067+
++it;
3068+
3069+
// Collect all arguments into a vector
3070+
std::vector<node_idx_t> arg_values;
3071+
for (; it; ++it) {
3072+
arg_values.push_back(*it);
3073+
}
3074+
3075+
// Process format string
3076+
size_t pos = 0;
3077+
size_t arg_index = 0;
3078+
3079+
while (pos < format_str.length()) {
3080+
if (format_str[pos] == '%' && pos + 1 < format_str.length()) {
3081+
if (format_str[pos + 1] == '%') {
3082+
// Escaped % character
3083+
printf("%%");
3084+
pos += 2;
3085+
} else {
3086+
// The next character is the format specifier (simplified approach)
3087+
char format_char = format_str[pos + 1];
3088+
3089+
if (arg_index >= arg_values.size()) {
3090+
warnf("printf: not enough arguments for format string\n");
3091+
return NIL_NODE;
3092+
}
3093+
3094+
node_idx_t arg = arg_values[arg_index++];
3095+
3096+
switch (format_char) {
3097+
case 'd':
3098+
case 'i':
3099+
printf("%lld", get_node_int(arg));
3100+
break;
3101+
case 'f':
3102+
case 'g':
3103+
printf("%g", get_node_float(arg));
3104+
break;
3105+
case 's':
3106+
{
3107+
node_t* str_node = get_node(arg);
3108+
if (str_node->type == NODE_STRING) {
3109+
printf("%s", str_node->t_string.c_str());
3110+
} else {
3111+
printf("%s", get_node_string(arg).c_str());
3112+
}
3113+
}
3114+
break;
3115+
default:
3116+
// Just add the argument's string representation
3117+
printf("%s", get_node_string(arg).c_str());
3118+
break;
3119+
}
3120+
pos += 2; // Move past the % and the format specifier
3121+
}
3122+
} else {
3123+
// Regular character - print directly
3124+
printf("%c", format_str[pos++]);
3125+
}
3126+
}
3127+
3128+
fflush(stdout);
3129+
return NIL_NODE;
3130+
}
30523131
static node_idx_t native_do(env_ptr_t env, list_ptr_t args) {
30533132
return eval_node_list(env, args);
30543133
}
@@ -6038,7 +6117,6 @@ static node_idx_t native_set_q(env_ptr_t env, list_ptr_t args) {
60386117
// Returns the first logical true value of (pred x) for any x in coll,
60396118
// else nil. One common idiom is to use a set as pred, for example
60406119
// this will return :fred if :fred is in the sequence, otherwise nil:
6041-
// (some #{:fred} coll)
60426120
static node_idx_t native_some(env_ptr_t env, list_ptr_t args) {
60436121
node_idx_t pred_idx = args->first_value();
60446122
node_idx_t coll_idx = args->second_value();
@@ -6541,6 +6619,7 @@ int main(int argc, char **argv) {
65416619
env->set("prn", new_node_native_function("prn", &native_prn, false, NODE_FLAG_PRERESOLVE));
65426620
env->set("pr-str", new_node_native_function("pr-str", &native_pr_str, false, NODE_FLAG_PRERESOLVE));
65436621
env->set("prn-str", new_node_native_function("prn-str", &native_prn_str, false, NODE_FLAG_PRERESOLVE));
6622+
env->set("printf", new_node_native_function("printf", &native_printf, false, NODE_FLAG_PRERESOLVE));
65446623
env->set("=", new_node_native_function("=", &native_eq, false, NODE_FLAG_PRERESOLVE));
65456624
env->set("==", new_node_native_function("==", &native_eq, false, NODE_FLAG_PRERESOLVE));
65466625
env->set("not=", new_node_native_function("not=", &native_neq, false, NODE_FLAG_PRERESOLVE));

jo_stdcpp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,9 @@ struct jo_string {
762762
return *this;
763763
}
764764

765+
char &operator[](size_t n) { return str[n]; }
766+
const char &operator[](size_t n) const { return str[n]; }
767+
765768
size_t find_last_of(char c) const {
766769
for(long long i = size - 2; i >= 0; --i) {
767770
if(str[i] == c) return i;

0 commit comments

Comments
 (0)