summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2026-06-05 20:32:17 -0400
committerLLLL Colonq <llll@colonq>2026-06-05 20:32:17 -0400
commitb456aa44a172171d4b6120ec566c1499ec25a690 (patch)
tree7a835e42351ffd39e5620f5d8e705ef8c69d838e
parent48ab2cb8e3de88dbd0722337bd4617ad22de1a12 (diff)
Fix integer parsing
-rw-r--r--emacs/pit.el56
-rw-r--r--src/lexer.c37
-rw-r--r--src/parser.c11
-rw-r--r--src/utils.c1
-rw-r--r--test/int.pit1
5 files changed, 94 insertions, 12 deletions
diff --git a/emacs/pit.el b/emacs/pit.el
index cce2694..9a357a3 100644
--- a/emacs/pit.el
+++ b/emacs/pit.el
@@ -82,5 +82,61 @@
(setq-local c/contextual-ide 'pit/ide/body))
(add-hook 'pit/mode-hook #'pit/setup)
+;;;; nrepl client
+;; (require 'nrepl-client)
+;; (defun pit/repl/connect (&optional host port)
+;; "Connect to pit nREPL server at HOST:PORT."
+;; (let ((ret (get-buffer-create (generate-new-buffer-name " *pit-nrepl*") t)))
+;; (nrepl-start-client-process (or host "localhost") (or port 7888) nil (lambda (_pl) ret))
+;; ret))
+
+(require 'cider)
+(defun pit/repl/connect (&optional host port)
+ "Connect to pit nREPL server at HOST:PORT."
+ (let ( (dir (if-let* ((p (project-current))) (project-root p) default-directory))
+ (cider-repl-init-code nil))
+ (cider-nrepl-connect
+ (print
+ (thread-first `(:host ,host :port ,port :project-dir ,dir :repl-init-function nil :session-name nil :repl-type pit)
+ (cider--update-project-dir)
+ (cider--update-host-port)
+ (cider--check-existing-session))))))
+
+(defun cider-repl-handler (buffer)
+ "Make an nREPL evaluation handler for the REPL BUFFER."
+ (message "running cider-repl-handler")
+ (let ((show-prompt t))
+ (nrepl-make-response-handler
+ buffer
+ (lambda (buffer value)
+ (message "value-handler")
+ (cider-repl-emit-result buffer value t))
+ (lambda (buffer out)
+ (dolist (f cider--repl-stdout-functions)
+ (funcall f buffer out))
+ (cider-repl-emit-stdout buffer out))
+ (lambda (buffer err)
+ (dolist (f cider--repl-stderr-functions)
+ (funcall f buffer err))
+ (cider-repl-emit-stderr buffer err))
+ (lambda (buffer)
+ (message "done-handler: %s" show-prompt)
+ (when show-prompt
+ (cider-repl-emit-prompt buffer))
+ (when cider-repl-buffer-size-limit
+ (cider-repl-maybe-trim-buffer buffer))
+ (dolist (f cider--repl-done-functions)
+ (funcall f buffer)))
+ nrepl-err-handler
+ (lambda (buffer value content-type)
+ (if-let* ((content-attrs (cadr content-type))
+ (content-type* (car content-type))
+ (handler (cdr (assoc content-type*
+ cider-repl-content-type-handler-alist))))
+ (setq show-prompt (funcall handler content-type buffer value nil t))
+ (cider-repl-emit-result buffer value t t)))
+ (lambda (buffer warning)
+ (cider-repl-emit-stderr buffer warning)))))
+
(provide 'pit)
;;; pit.el ends here
diff --git a/src/lexer.c b/src/lexer.c
index adfe8d3..5d9c5e7 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -1,6 +1,7 @@
#include <lcq/pit/utils.h>
#include <lcq/pit/lexer.h>
#include <lcq/pit/types.h>
+#include <stdio.h>
const char *PIT_LEX_TOKEN_NAMES[PIT_LEX_TOKEN__SENTINEL] = {
/* [PIT_LEX_TOKEN_EOF] = */ "eof",
@@ -92,20 +93,34 @@ restart:
}
advance(st);
return PIT_LEX_TOKEN_STRING_LITERAL;
- default:
+ default: {
if (pit_ctype_isspace(c)) goto restart;
- if (pit_ctype_isdigit(c)) {
- if (c == '0') {
- int next = peek(st);
- if (next != 'x' && next != 'o' && next != 'b') return PIT_LEX_TOKEN_INTEGER_LITERAL;
- advance(st); /* skip base specifier */
- }
- while (match(st, is_hexdigit)) {}
- return PIT_LEX_TOKEN_INTEGER_LITERAL;
+ pit_lex_token ret = PIT_LEX_TOKEN_INTEGER_LITERAL;
+ int num_idx = 0;
+ bool leading_dash = false;
+ bool zero_prefix = false;
+ if (!is_symchar(c)) {
+ st->error = "unknown character";
+ return PIT_LEX_TOKEN_ERROR;
} else {
- while (match(st, is_symchar)) {}
- return PIT_LEX_TOKEN_SYMBOL;
+ do {
+ leading_dash = false;
+ switch (num_idx) {
+ case 0:
+ if (c == '0') zero_prefix = true;
+ else if (c == '-') { leading_dash = true; continue; }
+ break;
+ case 1:
+ if (zero_prefix && (c == 'x' || c == 'o' || c == 'b')) continue;
+ break;
+ }
+ if (!is_hexdigit(c)) ret = PIT_LEX_TOKEN_SYMBOL;
+ ++num_idx;
+ } while (c = peek(st), match(st, is_symchar));
}
+ if (leading_dash) return PIT_LEX_TOKEN_SYMBOL;
+ return ret;
+ }
}
}
diff --git a/src/parser.c b/src/parser.c
index 5dc57db..77b4172 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -129,7 +129,16 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st, bool *eof) {
i64 idx = st->cur.start;
i64 base = 10;
i64 total = 0;
+ bool neg = false;
char c = st->lexer->input[idx++];
+ if (c == '-') {
+ neg = true;
+ if (idx < st->cur.end) {
+ c = st->lexer->input[idx++];
+ } else {
+ pit_error(rt, "malformed negative integer literal"); return PIT_NIL;
+ }
+ }
if (c == '0' && idx + 1 < st->cur.end) {
switch (st->lexer->input[idx++]) {
case 'b': base = 2; break;
@@ -145,7 +154,7 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st, bool *eof) {
pit_error(rt, "integer literal too large"); return PIT_NIL;
}
}
- return pit_integer_new(rt, total);
+ return pit_integer_new(rt, neg ? -total : total);
}
case PIT_LEX_TOKEN_STRING_LITERAL: {
char buf[256] = {0};
diff --git a/src/utils.c b/src/utils.c
index 7f2831b..53a9ebf 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -45,6 +45,7 @@ int pit_string_vsnprintf(char *buf, size_t len, char *format, va_list ap) {
if (length_mod == 'l') arg = va_arg(ap, long); else arg = va_arg(ap, int);
if (arg == 0) { WRITE('0') }
else {
+ if (arg < 0) { WRITE('-'); arg = -arg; }
while (arg != 0) { WRITE_SCRATCH('0' + (char) (arg % 10)); arg /= 10; }
while (sidx > 0) { WRITE(scratch[sidx - 1]); sidx -= 1; }
}
diff --git a/test/int.pit b/test/int.pit
new file mode 100644
index 0000000..65646af
--- /dev/null
+++ b/test/int.pit
@@ -0,0 +1 @@
+(print! 0x10)