-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.lisp
142 lines (107 loc) · 3.49 KB
/
common.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
;;;; -*- Mode: Lisp -*-
;;;;
;;;; Copyright (c) 2008-2009 Arturs Grebstelis
;;;;
(defpackage #:abop
(:use #:common-lisp))
(in-package #:abop)
(declaim (inline sfloat float-equal))
(defun sfloat (value) (coerce value 'single-float))
(defun float-equal (f1 f2)
(> single-float-epsilon (abs (- f1 f2))))
(defun to-radians (angle)
(sfloat (* angle (/ pi 180.0))))
(export 'to-degrees)
(defun to-degrees (angle)
(sfloat (* (/ angle pi) 180.0)))
(defun unit-random ()
(/ (random most-positive-fixnum)
(sfloat (1- most-positive-fixnum))))
(defun file-probe (name)
(open name :direction :probe))
(defun indexed-name (prefix extension &optional (number 0) (fn #'file-probe))
(let ((name (format nil "~A-~5,'0d~A" prefix number extension)))
(if (funcall fn name)
(indexed-name prefix extension (incf number) fn)
name)))
(export 'setf-if-nil)
(defmacro setf-if-nil (x y)
`(or ,x (setf ,x ,y)))
(defun is-whitespace (char)
(member char '(#\space #\tab #\newline)))
(defun read-word (stream)
(peek-char t stream)
(with-output-to-string (out)
(loop for c = (peek-char nil stream) do
(unless (and c (not (is-whitespace c)))
(loop-finish))
(write-char c out)
(read-char stream))))
(export 'map-array)
(defun map-array (array fn)
(dotimes (i (length array))
(funcall fn (aref array i))))
(defun length=1 (x)
(and (consp x) (null (cdr x))))
(defun sym (&rest args)
(intern (format nil "~{~a~}" args)))
(export '*stream*)
(defvar *stream* nil)
(export 'file-safety-net)
(defun file-safety-net (name fn)
(handler-case
(with-open-file (*stream* name :direction :output :if-exists :supersede)
(funcall fn))
(file-error () (format t "ERROR: could not write ~A~%" name))
(:no-error (ret) (progn (format t "done saving ~A~%" name) ret))))
(defun first-or-self (something)
(if (consp something)
(first something)
something))
(export 'new-symbol)
(defun new-symbol (&rest args)
(intern (format nil "~{~a~}" args)))
(defun slot-symbols (name slots)
(mapcar (lambda (slot) (new-symbol name "-" (first-or-self slot))) slots))
(defmacro def-exported-struct (name-and-options &rest slots)
(let ((name (first-or-self name-and-options)))
`(progn
(defstruct ,name-and-options ,@slots)
(export '(,(new-symbol "MAKE-" name)
,@(slot-symbols name slots))))))
(export 'concstrs)
(defun concstrs (&rest strings)
(apply #'concatenate (cons 'string strings)))
(defun dbg (x)
(format t "~A~%" x)
x)
(cffi:defcfun ("noise3D" noise3D) :float
(x :float)
(y :float)
(z :float))
(defun noise (p)
(noise3D (point-x p) (point-y p) (point-z p)))
;; --- queue ------------------------------------------------------------------
(defstruct queue length start tail)
(defun create-queue (&optional some-list)
(let ((head-list (cons :head some-list)))
(make-queue :length (length some-list)
:tail (last head-list)
:start head-list)))
(defun get-queue-head (queue)
(cdr (queue-start queue)))
(defun attach-to-queue (queue some-list)
(when some-list
(nconc (queue-tail queue) some-list)
(setf (queue-tail queue) (last some-list))
(incf (queue-length queue) (length some-list)))
queue)
;; --- generic wrapper --------------------------------------------------------
(defvar *clean-up* nil)
(defmacro clean-up-forms (&body commands)
`(push (lambda () ,@commands) *clean-up*))
(defmacro with-system (&body body)
`(let ((*clean-up* nil))
(unwind-protect
(progn ,@body (values))
(mapc #'funcall *clean-up*))))