Merge branch 'master' into lifetimez-with-lambdas

This commit is contained in:
Erik Svedäng 2020-02-07 14:34:13 +01:00
commit 4fe7ea072b
84 changed files with 2816 additions and 271 deletions

View File

@ -47,7 +47,7 @@ The Carp REPL has built-in documentation, run ```(help)``` to access it!
(SDLApp.run-with-callbacks &app SDLApp.quit-on-esc tick draw state)))
```
To build this example, save it to a file called 'example.carp' and load it with ```(load "example.carp")```, then execute ```(build)``` to build an executable, and ```(run)``` to start. The external dependencies are SDL2 and pkg-config.
To build this example, save it to a file called 'example.carp' and load it with ```(load "example.carp")```, then execute ```(build)``` to build an executable, and ```(run)``` to start. The external dependencies are SDL2 and pkg-config. On macOS Catalina libiconv is also required.
### Language Designer & Lead Developer
[Erik Svedäng](http://www.eriksvedang.com) ([@e_svedang](https://twitter.com/e_svedang))
@ -72,7 +72,7 @@ Are you missing from the contributors list? Please send a pull request!
## License
Copyright 2016 - 2019 Erik Svedäng
Copyright 2016 - 2020 Erik Svedäng
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -25,7 +25,7 @@ defaultProject =
, projectEchoC = False
, projectLibDir = "libs"
, projectCarpDir = "."
, projectOutDir = "out/"
, projectOutDir = "out"
, projectDocsDir = "docs"
, projectDocsLogo = ""
, projectDocsPrelude = ""
@ -57,31 +57,30 @@ main = do setLocaleEncoding utf8
noCore = NoCore `elem` otherOptions
optimize = Optimize `elem` otherOptions
generateOnly = GenerateOnly `elem` otherOptions
projectWithFiles = defaultProject { projectCFlags = (if logMemory then ["-D LOG_MEMORY"] else []) ++
(if optimize then ["-O3 -D NDEBUG"] else []) ++
(projectCFlags defaultProject),
projectWithFiles = defaultProject { projectCFlags = ["-D LOG_MEMORY" | logMemory] ++
["-O3 -D NDEBUG" | optimize] ++
projectCFlags defaultProject,
projectCore = not noCore,
projectGenerateOnly = generateOnly}
noArray = False
coreModulesToLoad = if noCore then [] else (coreModules (projectCarpDir projectWithCarpDir))
coreModulesToLoad = if noCore then [] else coreModules (projectCarpDir projectWithCarpDir)
projectWithCarpDir = case lookup "CARP_DIR" sysEnv of
Just carpDir -> projectWithFiles { projectCarpDir = carpDir }
Nothing -> projectWithFiles
projectWithCustomPrompt = setCustomPromptFromOptions projectWithCarpDir otherOptions
startingContext = (Context
startingContext = Context
(startingGlobalEnv noArray)
(TypeEnv startingTypeEnv)
[]
projectWithCustomPrompt
""
execMode)
execMode
context <- loadFiles startingContext coreModulesToLoad
carpProfile <- configPath "profile.carp"
hasProfile <- doesFileExist carpProfile
context' <- if hasProfile
then loadFiles context [carpProfile]
else do --putStrLn ("No '" ++ carpProfile ++ "' found.")
return context
else return context
finalContext <- loadFiles context' argFilesToLoad
settings <- readlineSettings (bindingNames $ contextGlobalEnv finalContext)
case execMode of
@ -99,7 +98,7 @@ main = do setLocaleEncoding utf8
BuildAndRun -> do _ <- executeString True finalContext ":bx" "Compiler (Build & Run)"
-- TODO: Handle the return value from executeString and return that one to the shell
return ()
Check -> do return ()
Check -> return ()
-- | Options for how to run the compiler.
data OtherOptions = NoCore

View File

@ -6,7 +6,7 @@ As an example, consider this definition of `sum` based on `reduce`:
```
(defn sum [x]
(reduce + 0 x))
(reduce &(fn [x y] (+ x @y)) 0 x))
```
It will sum the previous sum with each new value, starting at `0`.")
@ -257,6 +257,24 @@ This function copies the array. If you dont want that, use [`endo-map`](#endo
(aset-uninitialized! &na i (~f (unsafe-nth a i))))
na))
(doc unreduce "creates an array by producing values using `step` until they
no longer satisfy `test`. The initial value is `start`.
Example:
```
; if we didnt have Array.range, we could define it like this:
(defn range [start end step]
(unreduce start &(fn [x] (< x (+ step end))) &(fn [x] (+ x step)))
)
```")
(defn unreduce [start test step]
(let-do [elem start
acc []]
(while-do (~test elem)
(push-back! &acc elem)
(set! elem (~step elem)))
acc))
(doc zip "maps over two arrays using a function `f` that takes two arguments. It will produces a new array with the length of the shorter input.
The trailing elements of the longer array will be discarded.")

View File

@ -1,13 +1,16 @@
(load "Statistics.carp")
(system-include "carp_bench.h")
(register get-time-elapsed (Fn [] Double))
(defmodule Bench
(def min-runs 50)
(private min-runs)
(hidden min-runs)
(private get-time-elapsed)
(hidden get-time-elapsed)
(register get-time-elapsed (Fn [] Double) "get_time_elapsed")
(doc set-min-runs! "sets the minimum number of runs to `n`.
If your functions takes a large amount of time, experimenting with this might make sense. The default value is `50`, which means that your function runs at least `50` times before even hitting a timeout.")
@ -106,15 +109,15 @@ If your functions takes a large amount of time, experimenting with this might ma
(defmacro benchn [n form]
(list 'let ['before (get-time-elapsed)
(list 'let ['before (Bench.get-time-elapsed)
'times []]
(list 'do
(list 'for ['i 0 n]
(list 'let ['before-once (get-time-elapsed)]
(list 'let ['before-once (Bench.get-time-elapsed)]
(list 'do
form
(list 'set! &times (Array.push-back (Array.copy &times) (Double.- (get-time-elapsed) before-once))))))
(list 'let ['total (Double.- (get-time-elapsed) before)
(list 'set! &times (Array.push-back (Array.copy &times) (Double.- (Bench.get-time-elapsed) before-once))))))
(list 'let ['total (Double.- (Bench.get-time-elapsed) before)
'per (list 'Double./ 'total (list 'Double.from-int n))]
(do
(Bench.print "Total time elapsed: " total)

61
core/Byte.carp Normal file
View File

@ -0,0 +1,61 @@
(system-include "carp_byte.h")
(defmodule Byte
(register + (λ [Byte Byte] Byte))
(register - (λ [Byte Byte] Byte))
(register * (λ [Byte Byte] Byte))
(register / (λ [Byte Byte] Byte))
(register < (λ [Byte Byte] Bool))
(register > (λ [Byte Byte] Bool))
(register = (λ [Byte Byte] Bool))
(register mod (λ [Byte Byte] Byte))
(register bit-shift-left (λ [Byte Byte] Byte))
(register bit-shift-right (λ [Byte Byte] Byte))
(register bit-and (λ [Byte Byte] Byte))
(register bit-or (λ [Byte Byte] Byte))
(register bit-xor (λ [Byte Byte] Byte))
(register bit-not (λ [Byte] Byte))
(register inc (λ [Byte] Byte))
(register dec (λ [Byte] Byte))
(register copy (λ [&Byte] Byte))
(register to-int (λ [Byte] Int))
(register from-int (λ [Int] Byte))
(defn even? [a] (= (mod a 2b) 0b))
(defn odd? [a] (not (even? a)))
(defn zero [] 0b)
(defn add-ref [x y]
(Byte.+ @x @y))
;; Move to generic math module?
(defn clamp [min, max, val]
(if (> val max)
max
(if (< val min)
min
val)))
(doc pow "Raise x to the power of y.")
(defn pow [x y]
(let-do [r 1b]
(while (/= y 0b)
(do
(when (/= (bit-and y 1b) 0b)
(set! r (* r x)))
(set! y (/ y 2b))
(set! x (* x x))))
r))
)
(defmodule ByteRef
(defn = [a b]
(Byte.= @a @b))
(defn < [a b]
(Byte.< @a @b))
(defn > [a b]
(Byte.> @a @b))
)

View File

@ -44,8 +44,7 @@
(defn alphanum? [c]
(or (alpha? c) (num? c)))
(defn zero []
(from-int 0))
(defn zero [] (the Char (from-int 0)))
)
(defmodule CharRef

View File

@ -12,8 +12,12 @@
(system-include "carp_stdbool.h")
(system-include "core.h")
(system-include "carp_memory.h")
(system-include "sys/wait.h")
(system-include "unistd.h")
(if (not (Dynamic.or (= "windows" (os)) (= "mingw32" (os))))
(do
(system-include "sys/wait.h")
(system-include "unistd.h"))
())
(load "Interfaces.carp")
(load "Bool.carp")
@ -23,6 +27,7 @@
(load "Result.carp")
(load "Dynamic.carp")
(load "Format.carp")
(load "Byte.carp")
(load "Int.carp")
(load "Long.carp")
(load "Double.carp")
@ -31,10 +36,11 @@
(load "Array.carp")
(load "Char.carp")
(load "String.carp")
(load "IO.carp")
(load "System.carp")
(load "IO.carp")
(load "Pattern.carp")
(load "Debug.carp")
(load "Pointer.carp")
(load "Format.carp")
(load "Random.carp")
(load "Map.carp")

View File

@ -5,32 +5,34 @@
len (String.length s)]
(if (= idx -1)
(list 'copy s) ; no more splits found, just return string
(if (= \% (String.char-at s (inc idx))) ; this is an escaped %
(list 'ref
(list 'String.append
"%"
(fmt-internal (String.substring s (+ idx 2) len) args)))
(if (= 0 (length args)) ; we need to insert something, but have nothing
(macro-error
(str "error in format string: not enough arguments to format string (missing argument for '%"
(String.substring s (inc idx) (inc (inc idx)))
"')"))
; okay, this is the meat:
; get the next % after our escaper
(let [next (String.index-of (String.substring s (inc idx) len) \%)]
(if (= -1 next)
(if (< 1 (length args))
(macro-error
(str "error in format string: too many arguments to format string (missing directive for '"
(cadr args)
"')"))
(list 'ref (list 'format s (car args))))
(let [slice (String.substring s 0 (+ (inc idx) next))]
(list 'ref
(list 'String.append
(list 'ref (list 'format slice (car args)))
(fmt-internal (String.substring s (+ (inc idx) next) len)
(cdr args))))))))))))
(if (= len 1)
(macro-error "error in format string: expected expression after last %")
(if (= \% (String.char-at s (inc idx))) ; this is an escaped %
(list 'ref
(list 'String.append
"%"
(fmt-internal (String.substring s (+ idx 2) len) args)))
(if (= 0 (length args)) ; we need to insert something, but have nothing
(macro-error
(str "error in format string: not enough arguments to format string (missing argument for '%"
(String.substring s (inc idx) (inc (inc idx)))
"')"))
; okay, this is the meat:
; get the next % after our escaper
(let [next (String.index-of (String.substring s (inc idx) len) \%)]
(if (= -1 next)
(if (< 1 (length args))
(macro-error
(str "error in format string: too many arguments to format string (missing directive for '"
(cadr args)
"')"))
(list 'ref (list 'format s (car args))))
(let [slice (String.substring s 0 (+ (inc idx) next))]
(list 'ref
(list 'String.append
(list 'ref (list 'format slice (car args)))
(fmt-internal (String.substring s (+ (inc idx) next) len)
(cdr args)))))))))))))
(doc fmt "formats a string. It supports all of the string interpolations defined in format of the type that should be interpolated (e.g. %d and %x on integers).")
(defmacro fmt [s :rest args]

View File

@ -74,6 +74,7 @@ The margin of error is 0.00001.")
(not (neg? x)))
(defn id [x] x)
(defn const [x] (fn [_] x))
(defn null? [p]
(Pointer.eq NULL (the (Ptr t) p)))
@ -106,4 +107,4 @@ The margin of error is 0.00001.")
(defn /= [a b]
(not (= a b)))
)
)

View File

@ -24,8 +24,17 @@
(register exit (Fn [Int] a))
(register EOF Char)
(doc EOF "the End-Of-File character as a literal.")
(doc fopen "opens a file by name using a mode (one or multiple of [r]ead, [w]rite, and [a]ppend), returns a file pointer.")
(doc fopen "opens a file by name using a mode (one or multiple of [r]ead, [w]rite, and [a]ppend), returns a file pointer. Consider using the function open-file instead.")
(register fopen (Fn [&String &String] (Ptr FILE)))
(doc open-file "opens a file by name using a mode (one or multiple of [r]ead, [w]rite, and [a]ppend), returns a Result type that contains an error string or a file pointer.")
(defn open-file [filename mode]
(let [ptr (IO.fopen filename mode)]
(if (null? ptr)
(do
(Result.Error System.errno))
(Result.Success ptr))))
(doc fclose "closes a file pointer.")
(register fclose (Fn [(Ptr FILE)] ()))
(doc fgetc "gets a character from a file pointer.")
@ -51,15 +60,24 @@
(doc read->EOF "reads a file given by name until the End-Of-File character is reached.")
(defn read->EOF [filename]
(let [f (IO.fopen filename "rb")]
(if (null? f)
(Result.Error (fmt "File “%s” couldnt be opened!" filename))
(let [c (zero)
r []]
(do
(while (do (set! c (IO.fgetc f))
(/= c IO.EOF))
(set! r (Array.push-back r c)))
(IO.fclose f)
(Result.Success (String.from-chars &r)))))))
(let [maybe (IO.open-file filename "rb")]
(match maybe
(Result.Error x) (Result.Error x)
(Result.Success f) (let [c (zero)
r []]
(do
(while (do (set! c (IO.fgetc f))
(/= c IO.EOF))
(set! r (Array.push-back r c)))
(IO.fclose f)
(Result.Success (String.from-chars &r)))))))
(private getenv-)
(hidden getenv-)
(register getenv- (Fn [String] (Ptr Char)) "getenv")
(defn getenv [s]
(let [e (getenv- s)]
(if (null? e)
(Maybe.Nothing)
(Maybe.Just (from-cstr e)))))
)

View File

@ -73,6 +73,25 @@
(defndynamic cdddar [pair] (cdr (cdr (cdr (car pair)))))
(defndynamic cddddr [pair] (cdr (cdr (cdr (cdr pair)))))
(defndynamic cxr [x pair]
(if (= (length x) 0)
(list 'quote pair)
(list
(if (= 'a (cadr x))
'car
(if (= 'd (cadr x))
'cdr
(macro-error "`cxr` expects either `a` or `d` symbols, got " (cadr x))))
(if (= 1 (car x))
(cxr (cddr x) pair)
(cxr (cons (- (car x) 1) (cdr x)) pair)))))
(defndynamic nthcdr [n pair]
(cxr (list (+ n 1) 'd) pair))
(defndynamic nthcar [n pair]
(cxr (list 1 'a n 'd) pair))
(defndynamic eval-internal [form]
(list 'do
(list 'defn 'main [] (list 'IO.println* form))
@ -129,8 +148,8 @@
(list
'let (array variable from)
(list
'while (list (if (< step (- step step)) '> '<) variable to)
(list
'while (list (if (< step (- step step)) '> '<) variable to)
(list
'do
(if (= (length body) 0)
()
@ -151,11 +170,14 @@
;; (list f (list 'Array.nth (list 'ref xs) 'i))))
(defndynamic foreach-internal [var xs expr]
(list 'let ['xs xs
'len (list 'Array.length 'xs)]
(list 'for ['i 0 'len]
(list 'let [var (list 'Array.unsafe-nth 'xs 'i)]
expr))))
(let [xsym (gensym-with 'xs)
len (gensym-with 'len)
i (gensym-with 'i)]
(list 'let [xsym xs
len (list 'Array.length xsym)]
(list 'for [i 0 len]
(list 'let [var (list 'Array.unsafe-nth xsym i)]
expr)))))
(defmacro foreach [binding expr]
(if (array? binding)
@ -342,3 +364,24 @@ The expression must be evaluable at compile time.")
(doc gensym "generates symbols dynamically as needed.")
(defndynamic gensym []
(gensym-with 'gensym-generated))
(doc until "executes `body` until the condition `cnd` is true.")
(defmacro until [cnd body]
(list 'while (list 'not cnd)
body))
(doc defdynamic-once "creates a dynamic variable and sets its value if it's not already defined.")
(defmacro defdynamic-once [var expr]
(list 'if (list 'defined? var)
()
(list 'defdynamic var expr)))
(defndynamic comp-internal [sym fns]
(if (= (length fns) 0)
sym
(list (car fns) (comp-internal sym (cdr fns)))))
(doc comp "composes the functions `fns` into one `fn`.")
(defmacro comp [:rest fns]
(let [x (gensym)]
(list 'fn [x] (comp-internal x fns))))

View File

@ -29,6 +29,10 @@
(defn hash [k] (to-int (the Char @k)))
)
(defmodule Byte
(defn hash [k] (to-int (the Byte @k)))
)
(defmodule Float
(defn hash [k] (to-bytes @k))
)
@ -69,10 +73,16 @@
(do (Array.aupdate! (entries &b) i &(fn [p] (Pair.set-b @p @val)))
b))
(defn set-idx! [b i val]
(Array.aupdate! (entries b) i &(fn [p] (Pair.set-b @p @val))))
(defn push-back [b k v]
(do (Array.push-back! (entries &b) (Pair.init-from-refs k v))
b))
(defn push-back! [b k v]
(Array.push-back! (entries b) (Pair.init-from-refs k v)))
(defn get [b k default-value]
(let [i (find b k)]
(if (<= 0 i)
@ -92,6 +102,12 @@
(set-idx b i v)
(push-back b k v))))
(defn put! [b k v]
(let [i (find b k)]
(if (<= 0 i)
(set-idx! b i v)
(push-back! b k v))))
(defn contains? [b k]
(<= 0 (find b k)))
@ -136,7 +152,7 @@
(let [idx (Int.positive-mod (hash k) @(n-buckets m))
b (buckets m)
n (Array.unsafe-nth b idx)]
(Array.aset! b idx (Bucket.put @n k v))))
(Bucket.put! n k v)))
(doc get-with-default "Get the value for the key k from map m. If it isnt found, the default is returned.")
(defn get-with-default [m k default-value]
@ -320,6 +336,9 @@
(set! nentries (Array.push-back nentries @e)))))
nentries))
(defn push-back! [b k]
(Array.push-back! (entries b) k))
(defn shrink [b k]
(if (contains? b k)
(set-entries @b (remove (entries b) k))
@ -359,7 +378,7 @@
b (buckets s)
n (Array.unsafe-nth b idx)]
(when (not (SetBucket.contains? n k))
(Array.aset! b idx (SetBucket.grow n @k)))))
(SetBucket.push-back! n @k))))
(doc length "Get the length of set s.")
(defn length [s]

View File

@ -7,7 +7,7 @@
(defn apply [a f]
(match a
(Nothing) (Nothing)
(Just x) (Just (f x))))
(Just x) (Just (~f x))))
(doc unsafe-from "is an unsafe unwrapper that will get the value from a `Just`. If `a` is `Nothing`, a runtime error will be generated.")
(defn unsafe-from [a]

4
core/Pointer.carp Normal file
View File

@ -0,0 +1,4 @@
(defmodule Pointer
(defn inc [a] (Pointer.add a 1l))
(defn dec [a] (Pointer.sub a 1l))
)

View File

@ -76,3 +76,12 @@
(defn random-sized [n]
(from-chars &(Array.repeat n &Char.random)))
)
(defmodule Byte
(defn random-between [lower upper]
(Byte.from-int (Int.random-between (Byte.to-int lower) (Byte.to-int upper))))
(defn random []
(Byte.from-int (Int.random)))
)

View File

@ -6,21 +6,27 @@
(doc apply "takes a `Result` `a` and applies functions to them, one in the case that it is an `Error`, one in the case that it is a `Success`.")
(defn apply [a success-f error-f]
(match a
(Success x) (Success (success-f x))
(Error x) (Error (error-f x))))
(Success x) (Success (~success-f x))
(Error x) (Error (~error-f x))))
(doc map "takes a `Result` and applies a function `f` to it if it is a `Success` type, and wraps it back up. In the case that it is an `Error`, it is returned as is.")
(defn map [a f]
(match a
(Success x) (Success (f x))
(Success x) (Success (~f x))
(Error x) (Error x)))
(doc map-error "takes a `Result` and applies a function `f` to it if it is an `Error` type, and wraps it back up. In the case that it is a `Success`, it is returned as is.")
(defn map-error [a f]
(match a
(Success x) (Success x)
(Error x) (Error (~f x))))
(doc and-then "takes a `Result` and applies a function `f` to it if it is a `Success` type. In the case that it is an `Error`, it is returned as is.
It is thus quite similar to [`map`](#map), but it will unwrap the value.")
(defn and-then [a f]
(match a
(Success x) (f x)
(Success x) (~f x)
(Error x) (Error x)))
(doc unwrap-or-zero "takes a `Result` and either unwraps it if it is a `Success`, or calls `zero`. `zero` must be defined on the `Success` type.")
@ -35,13 +41,13 @@ It is the inverse of [`and-then`](#and-then).")
(defn or-else [a f]
(match a
(Success x) (Success x)
(Error x) (f x)))
(Error x) (~f x)))
(doc unwrap-or-else "takes a `Result` and either unwraps it if it is a `Success`, or calls a function `f` on the value contained in the `Error`.")
(defn unwrap-or-else [a f]
(match a
(Success x) x
(Error x) (f x)))
(Error x) (~f x)))
(doc unsafe-from-success "is an unsafe unwrapper that will get the value from a `Success`. If `a` is an `Error`, a runtime error will be generated.")
(defn unsafe-from-success [a]

View File

@ -5,17 +5,16 @@
(not-on-windows
(add-pkg "sdl2"))
(defmodule SDL
(defmodule Windows
(defdynamic header-path "C:\\SDL2-2.0.9\\include")
(defdynamic library-path "C:\\SDL2-2.0.9\\lib\\x86\\")))
;; Only define these if they're not already defined (allows the user to pre-define them before including SDL.carp)
(defdynamic-once sdl-windows-header-path "C:\\SDL2-2.0.9\\include")
(defdynamic-once sdl-windows-library-path "C:\\SDL2-2.0.9\\lib\\x86\\")
(windows-only
;; Note - you'll still need the SDL2.dll to be able to run the executable
(add-cflag "-DSDL_MAIN_HANDLED")
(add-cflag "-Wno-pragma-pack")
(add-cflag (str "-I" SDL.Windows.header-path))
(add-lib (str "/link " SDL.Windows.library-path "SDL2.lib " SDL.Windows.library-path "SDL2main.lib")))
(add-cflag (str "-I" sdl-windows-header-path))
(add-lib (str "/link " sdl-windows-library-path "SDL2.lib "))) ;; sdl-windows-library-path "SDL2main.lib")))
;; Types
(register-type SDL_Keycode)

View File

@ -10,6 +10,7 @@
(register copy (Fn [&String] String))
(register length (Fn [&String] Int))
(register cstr (Fn [&String] (Ptr Char)))
(register from-cstr (Fn [(Ptr Char)] String))
(register str (Fn [&String] String))
(register prn (Fn [&String] String))
(register index-of (Fn [&String Char] Int))
@ -179,9 +180,16 @@
(register from-string (λ [&String] Int))
)
(defmodule Byte
(register str (Fn [Byte] String))
(register format (Fn [&String Byte] String))
(register from-string (λ [&String] Byte))
)
(defmodule Float
(register str (Fn [Float] String))
(register format (Fn [&String Float] String))
(register from-string (λ [&String] Float))
)
(defmodule Long
@ -193,6 +201,7 @@
(defmodule Double
(register str (Fn [Double] String))
(register format (Fn [&String Double] String))
(register from-string (λ [&String] Double))
)
(defmodule Char
@ -202,6 +211,7 @@
)
(defmodule Int (defn prn [x] (Int.str x)))
(defmodule Byte (defn prn [x] (Byte.str x)))
(defmodule IntRef
(defn prn [x] (Int.str @x))
(defn str [x] (Int.str @x))
@ -211,6 +221,11 @@
(defn prn [x] (Bool.str @x))
(defn str [x] (Bool.str @x)))
(defmodule ByteRef
(defn prn [x] (Byte.str @x))
(defn str [x] (Byte.str @x))
)
(defmodule Long (defn prn [x] (Long.str x)))
(defmodule Float (defn prn [x] (Float.str x)))
(defmodule Double (defn prn [x] (Double.str x)))

View File

@ -1,4 +1,5 @@
(system-include "carp_system.h")
(system-include "errno.h")
(defmodule System
(doc free "Frees an object. Should not be called except in direst circumstances.")
@ -28,4 +29,24 @@
(register signal-segv Int "SIGSEGV")
(register signal-term Int "SIGTERM")
(register abort (Fn [] ()) "abort")
(register errno Int "errno")
(register EACCES Int "EACCES")
(register EEXIST Int "EEXIST")
(register EINVAL Int "EINVAL")
(register EIO Int "EIO")
(register EISDIR Int "EISDIR")
(register ELOOP Int "ELOOP")
(register EMFILE Int "EMFILE")
(register ENAMETOOLONG Int "ENAMETOOLONG")
(register ENOENT Int "ENOENT")
(register ENOMEM Int "EINVAL")
(register ENOSPC Int "ENOSPC")
(register ENOSR Int "ENOSR")
(register ENOTDIR Int "ENOTDIR")
(register ENXIO Int "ENXIO")
(register EOVERFLOW Int "EOVERFLOW")
(register EROFS Int "EROFS")
(register EINTR Int "EINTR")
)

View File

@ -247,7 +247,7 @@
(doc dot "Get the dot product of the two vectors x and y.")
(defn dot [x y]
(Maybe.apply (zip * x y)
(fn [x] (Array.reduce &(fn [x y] (+ x @y)) (zero) (v &x)))))
&(fn [x] (Array.reduce &(fn [x y] (+ x @y)) (zero) (v &x)))))
(doc mag-sq "Get the squared magnitude of a vector.")
(defn mag-sq [o]
@ -259,7 +259,7 @@
(doc dist "Get the distance between the vectors a and b.")
(defn dist [a b]
(Maybe.apply (sub b a) (fn [s] (mag &s))))
(Maybe.apply (sub b a) &(fn [s] (mag &s))))
(doc normalize "Normalize a vector.")
(defn normalize [o]
@ -271,21 +271,21 @@
(doc angle-between "Get the angle between two vectors a and b.")
(defn angle-between [a b]
(Maybe.apply (VectorN.dot a b)
(fn [x]
&(fn [x]
(let [dmm (/ x (* (VectorN.mag a) (VectorN.mag b)))]
(acos (clamp--1-1 dmm))))))
(doc anti-parallel? "Check whether the two vectors a and b are anti-parallel.")
(defn anti-parallel? [a b]
(Maybe.apply (angle-between a b) (fn [x] (= x pi))))
(Maybe.apply (angle-between a b) &(fn [x] (= x pi))))
(doc parallel? "Check whether the two vectors a and b are parallel.")
(defn parallel? [a b]
(Maybe.apply (angle-between a b) (fn [x] (zero? x))))
(Maybe.apply (angle-between a b) &(fn [x] (zero? x))))
(doc perpendicular? "Check whether the two vectors a and b are perpendicular.")
(defn perpendicular? [a b]
(Maybe.apply (angle-between a b) (fn [x] (= x (Generics.half-pi)))))
(Maybe.apply (angle-between a b) &(fn [x] (= x (Generics.half-pi)))))
(doc vlerp "Linearly interpolate between the two vectors a and b by amnt (between 0 and 1).")
(defn vlerp [a b amnt]

View File

@ -1,4 +1,4 @@
double get_MINUS_time_MINUS_elapsed() {
double get_time_elapsed() {
struct timespec tv;
clock_gettime(CLOCK_REALTIME, &tv);
return 1000000000 * tv.tv_sec + tv.tv_nsec;

70
core/carp_byte.h Normal file
View File

@ -0,0 +1,70 @@
#include <stdint.h>
typedef uint8_t byte;
uint8_t Byte__PLUS_(uint8_t x, uint8_t y) {
return x + y;
}
uint8_t Byte__MINUS_(uint8_t x, uint8_t y) {
return x - y;
}
uint8_t Byte__MUL_(uint8_t x, uint8_t y) {
return x * y;
}
uint8_t Byte__DIV_(uint8_t x, uint8_t y) {
return x / y;
}
bool Byte__EQ_(uint8_t x, uint8_t y) {
return x == y;
}
bool Byte__LT_(uint8_t x, uint8_t y) {
return x < y;
}
bool Byte__GT_(uint8_t x, uint8_t y) {
return x > y;
}
uint8_t Byte_inc(uint8_t x) {
return x + 1;
}
uint8_t Byte_dec(uint8_t x) {
return x - 1;
}
uint8_t Byte_bit_MINUS_shift_MINUS_left(uint8_t x, uint8_t y) {
return x << y;
}
uint8_t Byte_bit_MINUS_shift_MINUS_right(uint8_t x, uint8_t y) {
return x >> y;
}
uint8_t Byte_bit_MINUS_and(uint8_t x, uint8_t y) {
return x & y;
}
uint8_t Byte_bit_MINUS_or(uint8_t x, uint8_t y) {
return x | y;
}
uint8_t Byte_bit_MINUS_xor(uint8_t x, uint8_t y) {
return x ^ y;
}
uint8_t Byte_bit_MINUS_not(uint8_t x) {
return ~x;
}
uint8_t Byte_copy(const uint8_t *x) {
return *x;
}
uint8_t Byte_mod(uint8_t x, uint8_t divider) {
return x % divider;
}
bool Byte_mask(uint8_t a, uint8_t b) {
return a & b;
}
int Byte_to_MINUS_int(uint8_t a) {
return a;
}
uint8_t Byte_from_MINUS_int(int a) {
return a;
}

View File

@ -670,13 +670,13 @@ Array Pattern_global_MINUS_match(Pattern *p, String *s) {
String Pattern_internal_add_char(String a, char b) {
if (!a) {
String buffer = CARP_MALLOC(2);
snprintf(buffer, 2, "%c", b);
sprintf(buffer, "%c", b);
return buffer;
}
int len = strlen(a) + 2;
String buffer = CARP_MALLOC(len);
snprintf(buffer, len, "%s%c", a, b);
sprintf(buffer, "%s%c", a, b);
CARP_FREE(a);
return buffer;
}
@ -747,7 +747,7 @@ String Pattern_substitute(Pattern *p, String *s, String *t, int ns) {
int l = strlen(res) + strlen(str) + 1;
String buffer = CARP_MALLOC(l);
snprintf(buffer, l, "%s%s", res, str);
sprintf(buffer, "%s%s", res, str);
CARP_FREE(res);
return buffer;
}
@ -773,7 +773,7 @@ String Pattern_str(Pattern *p) {
String Pattern_prn(Pattern *p) {
int n = strlen(*p) + 4;
String buffer = CARP_MALLOC(n);
snprintf(buffer, n, "#\"%s\"", *p);
sprintf(buffer, "#\"%s\"", *p);
return buffer;
}

View File

@ -80,7 +80,9 @@ String String_append(const String *a, const String *b) {
int lb = strlen(*b);
int total = la + lb + 1;
String buffer = CARP_MALLOC(total);
snprintf(buffer, total, "%s%s", *a, *b);
memcpy(buffer, *a, la);
memcpy(buffer+la, *b, lb);
buffer[la+lb] = '\0';
return buffer;
}
@ -92,6 +94,10 @@ char *String_cstr(const String *s) {
return *s;
}
String String_from_MINUS_cstr(char *s) {
return String_copy(&s);
}
String String_str(const String *s) {
return String_copy(s);
}
@ -99,7 +105,7 @@ String String_str(const String *s) {
String String_prn(const String *s) {
int n = strlen(*s) + 4;
String buffer = CARP_MALLOC(n);
snprintf(buffer, n, "@\"%s\"", *s);
sprintf(buffer, "@\"%s\"", *s);
return buffer;
}
@ -110,7 +116,7 @@ char String_char_MINUS_at(const String *s, int i) {
String String_format(const String *str, const String *s) {
int size = snprintf(NULL, 0, *str, *s) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, *str, *s);
sprintf(buffer, *str, *s);
return buffer;
}
@ -156,68 +162,76 @@ String Bool_str(bool b) {
String Bool_format(const String *str, bool b) {
int size = snprintf(NULL, 0, *str, b) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, *str, b);
sprintf(buffer, *str, b);
return buffer;
}
String Char_str(char c) {
String buffer = CARP_MALLOC(2);
snprintf(buffer, 2, "%c", c);
sprintf(buffer, "%c", c);
return buffer;
}
String Char_prn(char c) {
String buffer = CARP_MALLOC(3);
snprintf(buffer, 3, "\\%c", c);
sprintf(buffer, "\\%c", c);
return buffer;
}
String Char_format(const String *str, char b) {
int size = snprintf(NULL, 0, *str, b) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, *str, b);
sprintf(buffer, *str, b);
return buffer;
}
String Double_str(double x) {
int size = snprintf(NULL, 0, "%g", x) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, "%g", x);
sprintf(buffer, "%g", x);
return buffer;
}
String Double_format(const String *s, double x) {
int size = snprintf(NULL, 0, *s, x) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, *s, x);
sprintf(buffer, *s, x);
return buffer;
}
double Double_from_MINUS_string(const String *s) {
return strtod(*s, NULL);
}
String Float_str(float x) {
int size = snprintf(NULL, 0, "%gf", x) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, "%gf", x);
sprintf(buffer, "%gf", x);
return buffer;
}
String Float_format(const String *str, float x) {
int size = snprintf(NULL, 0, *str, x) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, *str, x);
sprintf(buffer, *str, x);
return buffer;
}
float Float_from_MINUS_string(const String *s) {
return strtof(*s, NULL);
}
String Int_str(int x) {
int size = snprintf(NULL, 0, "%d", x) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, "%d", x);
sprintf(buffer, "%d", x);
return buffer;
}
String Int_format(const String *str, int x) {
int size = snprintf(NULL, 0, *str, x) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, *str, x);
sprintf(buffer, *str, x);
return buffer;
}
@ -228,14 +242,14 @@ int Int_from_MINUS_string(const String *s) {
String Long_str(long x) {
int size = snprintf(NULL, 0, "%ldl", x) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, "%ldl", x);
sprintf(buffer, "%ldl", x);
return buffer;
}
String Long_format(const String *str, long x) {
int size = snprintf(NULL, 0, *str, x) + 1;
String buffer = CARP_MALLOC(size);
snprintf(buffer, size, *str, x);
sprintf(buffer, *str, x);
return buffer;
}
@ -243,6 +257,24 @@ long Long_from_MINUS_string(const String *s) {
return atol(*s);
}
String Byte_str(uint8_t x) {
int size = snprintf(NULL, 0, "%ub", x) + 1;
String buffer = CARP_MALLOC(size);
sprintf(buffer, "%ub", x);
return buffer;
}
String Byte_format(const String *str, uint8_t x) {
int size = snprintf(NULL, 0, *str, x) + 1;
String buffer = CARP_MALLOC(size);
sprintf(buffer, *str, x);
return buffer;
}
uint8_t Byte_from_MINUS_string(const String *s) {
return atoi(*s);
}
int String_index_MINUS_of_MINUS_from(const String *s, char c, int i) {
/* Return index of first occurrence of `c` in `s` AFTER index i
* Returns -1 if not found

View File

@ -1,6 +1,8 @@
#if defined(WIN32) || defined(_WIN32) || \
defined(__WIN32) && !defined(__CYGWIN__)
#include <BaseTsd.h>
#include <windows.h>
typedef SSIZE_T ssize_t;
#endif
#ifndef _WIN32
#include <unistd.h>
@ -12,15 +14,24 @@ typedef char *Pattern;
#if defined NDEBUG
#define CHK_INDEX(i, n)
#else
#define CHK_INDEX(i, n) \
do { \
size_t __si = (size_t)i; \
size_t __ni = (size_t)n; \
if (!(__si < __ni)) { \
printf(__FILE__ ":%u: bad index: %zd < %zd\n", __LINE__, \
(ssize_t)i, (ssize_t)n); \
abort(); \
} \
#if defined(WIN32) || defined(_WIN32) || \
defined(__WIN32) && !defined(__CYGWIN__)
// The %zd format flag doesn't seem to work on Windows?
#define CHK_INDEX_FORMAT_STRING ":%u: bad index: %ld < %ld\n"
#else
#define CHK_INDEX_FORMAT_STRING ":%u: bad index: %zd < %zd\n"
#endif
#define CHK_INDEX(i, n) \
do { \
size_t __si = (size_t)i; \
size_t __ni = (size_t)n; \
if (!(__si < __ni)) { \
printf(__FILE__ CHK_INDEX_FORMAT_STRING, __LINE__, (ssize_t)i, \
(ssize_t)n); \
abort(); \
} \
} while (0)
#endif

33
docs/DynamicSemantics.md Normal file
View File

@ -0,0 +1,33 @@
# Dynamic Semantics
This document will help us rewrite Carp's dynamic evaluator (defined in Eval.hs) to make it behave in a more principled and non-surprising way.
## Goals of the rewrite
* Fix the various bugs related to dynamic evaluation that has been found (see "Relevant issues" below).
* Add missing features that are to be expected in a dynamic Lisp (see below).
* Make it easy to extend the dynamic evaluator with new features in the future.
## Relevant issues
* https://github.com/carp-lang/Carp/issues/560
* https://github.com/carp-lang/Carp/issues/555
* https://github.com/carp-lang/Carp/issues/545
* https://github.com/carp-lang/Carp/issues/476
* https://github.com/carp-lang/Carp/issues/556
* https://github.com/carp-lang/Carp/issues/659
* https://github.com/carp-lang/Carp/issues/660
* https://github.com/carp-lang/Carp/issues/453
## Desired features (currently missing)
* Documentation on how to use the dynamic language and the macro system
* Complete macro facilities (quasiquoting, splicing, complete error reporting, etc)
* Dynamic stack traces
* Auto completion of user-defined names
<hr>
# Semantics
## Index
[TODO]
## 1. [TODO]

View File

@ -94,7 +94,7 @@ If-statements are kind of tricky in regards to memory management:
manage)))
```
The 'manage-me' variable is the return value in the second branch, but should get freed if "Too short" is returned.
The 'manage' variable is the return value in the second branch, but should get freed if "Too short" is returned.
The output is a somewhat noisy C program:
```C
string say_MINUS_what(string text) {

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
@ -139,7 +149,7 @@
Array
</h1>
<div class="module-description">
</div>
<div class="binder">
<a class="anchor" href="#=">
@ -194,7 +204,7 @@
(λ [Int] (Array a))
</p>
<span>
</span>
<p class="doc">
<p>allocates an uninitialized array. You can initialize members using <a href="#aset-uninitialized"><code>aset-uninitialized</code></a>.</p>
@ -234,7 +244,7 @@
(λ [(Array a), Int, a] (Array a))
</p>
<span>
</span>
<p class="doc">
<p>sets an array element at the index <code>n</code> to a new value.</p>
@ -254,7 +264,7 @@
(λ [(Ref (Array a) b), Int, a] ())
</p>
<span>
</span>
<p class="doc">
<p>sets an array element at the index <code>n</code> to a new value in place.</p>
@ -274,7 +284,7 @@
(λ [(Ref (Array a) b), Int, a] ())
</p>
<span>
</span>
<p class="doc">
<p>sets an uninitialized array member. The old member will not be deleted.</p>
@ -374,7 +384,7 @@
(λ [(Ref (Array a) b)] (Array a))
</p>
<span>
</span>
<p class="doc">
<p>copies an array.</p>
@ -436,7 +446,7 @@
(λ [(Array a)] ())
</p>
<span>
</span>
<p class="doc">
<p>deletes an array. This function should usually not be called manually.</p>
@ -496,7 +506,7 @@
(λ [(Ref ((λ a) [(Ref b c)] Bool) d), (Array b)] (Array b))
</p>
<span>
</span>
<p class="doc">
<p>filters array members using a function. This function takes ownership.</p>
@ -516,7 +526,7 @@
(λ [(Ref ((λ a) [b] b) c), (Array b)] (Array b))
</p>
<span>
</span>
<p class="doc">
<p>applies a function <code>f</code> to an array <code>a</code>. The type of the elements cannot change.</p>
@ -661,7 +671,7 @@
(λ [(Ref (Array a) b)] Int)
</p>
<span>
</span>
<p class="doc">
<p>gets the length of the array.</p>
@ -720,7 +730,7 @@
defn
</div>
<p class="sig">
(λ [(Ref (Array a) StaticLifetime), Int] (Maybe a))
(λ [(Ref (Array a)), Int] (Maybe a))
</p>
<pre class="args">
(nth xs index)
@ -744,7 +754,7 @@
(λ [(Array a)] (Array a))
</p>
<span>
</span>
<p class="doc">
<p>removes the last element of an array and returns the new array.</p>
@ -764,7 +774,7 @@
(λ [(Ref (Array a) b)] a)
</p>
<span>
</span>
<p class="doc">
<p>removes an element <code>value</code> from the end of an array <code>a</code> in-place and returns it.</p>
@ -827,7 +837,7 @@
(prn x)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
@ -843,7 +853,7 @@
(λ [(Array a), a] (Array a))
</p>
<span>
</span>
<p class="doc">
<p>adds an element <code>value</code> to the end of an array <code>a</code>.</p>
@ -863,7 +873,7 @@
(λ [(Ref (Array a) b), a] ())
</p>
<span>
</span>
<p class="doc">
<p>adds an element <code>value</code> to the end of an array <code>a</code> in-place.</p>
@ -903,7 +913,7 @@
(λ [(Array a)] (Ptr a))
</p>
<span>
</span>
<p class="doc">
<p>returns an array <code>a</code> as a raw pointer—useful for interacting with C.</p>
@ -929,7 +939,7 @@
<p>will reduce an array <code>xs</code> into a single value using a function <code>f</code> that takes the reduction thus far and the next value. The initial reduction value is <code>x</code>.</p>
<p>As an example, consider this definition of <code>sum</code> based on <code>reduce</code>:</p>
<pre><code>(defn sum [x]
(reduce + 0 x))
(reduce &amp;(fn [x y] (+ x @y)) 0 x))
</code></pre>
<p>It will sum the previous sum with each new value, starting at <code>0</code>.</p>
@ -1189,7 +1199,7 @@
(λ [(Ref (Array a) b)] String)
</p>
<span>
</span>
<p class="doc">
<p>converts an array to a string.</p>
@ -1316,6 +1326,33 @@
</p>
</div>
<div class="binder">
<a class="anchor" href="#unreduce">
<h3 id="unreduce">
unreduce
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [a, (Ref (λ [a] Bool)), (Ref (λ [a] a))] (Array a))
</p>
<pre class="args">
(unreduce start test step)
</pre>
<p class="doc">
<p>creates an array by producing values using <code>step</code> until they
no longer satisfy <code>test</code>. The initial value is <code>start</code>.</p>
<p>Example:</p>
<pre><code>; if we didnt have Array.range, we could define it like this:
(defn range [start end step]
(unreduce start &amp;(fn [x] (&lt; x (+ step end))) &amp;(fn [x] (+ x step)))
)
</code></pre>
</p>
</div>
<div class="binder">
<a class="anchor" href="#unsafe-first">
<h3 id="unsafe-first">
@ -1368,10 +1405,10 @@
template
</div>
<p class="sig">
(λ [(Ref (Array a) StaticLifetime), Int] (Ref a StaticLifetime))
(λ [(Ref (Array t)), Int] &amp;t)
</p>
<span>
</span>
<p class="doc">
<p>gets a reference to the <code>n</code>th element from an array <code>a</code>.</p>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

765
docs/core/Byte.html Normal file
View File

@ -0,0 +1,765 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="carp_style.css">
</head>
<body>
<div class="content">
<div class="logo">
<a href="http://github.com/carp-lang/Carp">
<img src="logo.png">
</a>
<div class="title">
core
</div>
<div class="index">
<ul>
<li>
<a href="Dynamic.html">
Dynamic
</a>
</li>
<li>
<a href="Int.html">
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
</a>
</li>
<li>
<a href="Bool.html">
Bool
</a>
</li>
<li>
<a href="Float.html">
Float
</a>
</li>
<li>
<a href="Double.html">
Double
</a>
</li>
<li>
<a href="Vector2.html">
Vector2
</a>
</li>
<li>
<a href="Vector3.html">
Vector3
</a>
</li>
<li>
<a href="VectorN.html">
VectorN
</a>
</li>
<li>
<a href="Geometry.html">
Geometry
</a>
</li>
<li>
<a href="Statistics.html">
Statistics
</a>
</li>
<li>
<a href="String.html">
String
</a>
</li>
<li>
<a href="Char.html">
Char
</a>
</li>
<li>
<a href="Pattern.html">
Pattern
</a>
</li>
<li>
<a href="Array.html">
Array
</a>
</li>
<li>
<a href="IO.html">
IO
</a>
</li>
<li>
<a href="System.html">
System
</a>
</li>
<li>
<a href="Debug.html">
Debug
</a>
</li>
<li>
<a href="Test.html">
Test
</a>
</li>
<li>
<a href="Bench.html">
Bench
</a>
</li>
<li>
<a href="Map.html">
Map
</a>
</li>
<li>
<a href="Maybe.html">
Maybe
</a>
</li>
<li>
<a href="Result.html">
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
<h1>
Byte
</h1>
<div class="module-description">
</div>
<div class="binder">
<a class="anchor" href="#*">
<h3 id="*">
*
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#+">
<h3 id="+">
+
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#-">
<h3 id="-">
-
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#/">
<h3 id="/">
/
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#&lt;">
<h3 id="&lt;">
&lt;
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Bool)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#=">
<h3 id="=">
=
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Bool)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#&gt;">
<h3 id="&gt;">
&gt;
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Bool)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#add-ref">
<h3 id="add-ref">
add-ref
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [&amp;Byte, &amp;Byte] Byte)
</p>
<pre class="args">
(add-ref x y)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#bit-and">
<h3 id="bit-and">
bit-and
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#bit-not">
<h3 id="bit-not">
bit-not
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#bit-or">
<h3 id="bit-or">
bit-or
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#bit-shift-left">
<h3 id="bit-shift-left">
bit-shift-left
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#bit-shift-right">
<h3 id="bit-shift-right">
bit-shift-right
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#bit-xor">
<h3 id="bit-xor">
bit-xor
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#clamp">
<h3 id="clamp">
clamp
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [a, a, a] a)
</p>
<pre class="args">
(clamp min max val)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#copy">
<h3 id="copy">
copy
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [&amp;Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#dec">
<h3 id="dec">
dec
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#even?">
<h3 id="even?">
even?
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [Byte] Bool)
</p>
<pre class="args">
(even? a)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#format">
<h3 id="format">
format
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [&amp;String, Byte] String)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#from-int">
<h3 id="from-int">
from-int
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Int] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#from-string">
<h3 id="from-string">
from-string
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [&amp;String] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#hash">
<h3 id="hash">
hash
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [&amp;Byte] Int)
</p>
<pre class="args">
(hash k)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#inc">
<h3 id="inc">
inc
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#mod">
<h3 id="mod">
mod
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#odd?">
<h3 id="odd?">
odd?
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [Byte] Bool)
</p>
<pre class="args">
(odd? a)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#pow">
<h3 id="pow">
pow
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<pre class="args">
(pow x y)
</pre>
<p class="doc">
<p>Raise x to the power of y.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#prn">
<h3 id="prn">
prn
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [Byte] String)
</p>
<pre class="args">
(prn x)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#random">
<h3 id="random">
random
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [] Byte)
</p>
<pre class="args">
(random)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#random-between">
<h3 id="random-between">
random-between
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [Byte, Byte] Byte)
</p>
<pre class="args">
(random-between lower upper)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#str">
<h3 id="str">
str
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte] String)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#to-int">
<h3 id="to-int">
to-int
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [Byte] Int)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#zero">
<h3 id="zero">
zero
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [] Byte)
</p>
<pre class="args">
(zero)
</pre>
<p class="doc">
</p>
</div>
</div>
</body>
</html>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
@ -499,7 +509,7 @@
defn
</div>
<p class="sig">
(λ [] a)
(λ [] Char)
</p>
<pre class="args">
(zero)

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
@ -675,6 +685,25 @@
</p>
</div>
<div class="binder">
<a class="anchor" href="#from-string">
<h3 id="from-string">
from-string
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [&amp;String] Double)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#hash">
<h3 id="hash">

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
@ -1112,6 +1122,25 @@
</p>
</div>
<div class="binder">
<a class="anchor" href="#cxr">
<h3 id="cxr">
cxr
</h3>
</a>
<div class="description">
dynamic
</div>
<p class="sig">
Dynamic
</p>
<pre class="args">
(cxr x pair)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#dec">
<h3 id="dec">
@ -1435,6 +1464,44 @@
</p>
</div>
<div class="binder">
<a class="anchor" href="#nthcar">
<h3 id="nthcar">
nthcar
</h3>
</a>
<div class="description">
dynamic
</div>
<p class="sig">
Dynamic
</p>
<pre class="args">
(nthcar n pair)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#nthcdr">
<h3 id="nthcdr">
nthcdr
</h3>
</a>
<div class="description">
dynamic
</div>
<p class="sig">
Dynamic
</p>
<pre class="args">
(nthcdr n pair)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#os">
<h3 id="os">

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
@ -637,6 +647,25 @@
</p>
</div>
<div class="binder">
<a class="anchor" href="#from-string">
<h3 id="from-string">
from-string
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [&amp;String] Float)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#hash">
<h3 id="hash">

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
@ -139,7 +149,7 @@
IO
</h1>
<div class="module-description">
</div>
<div class="binder">
<a class="anchor" href="#EOF">
@ -154,7 +164,7 @@
Char
</p>
<span>
</span>
<p class="doc">
<p>the End-Of-File character as a literal.</p>
@ -174,10 +184,10 @@
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
@ -193,10 +203,10 @@
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
@ -212,10 +222,10 @@
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
@ -271,7 +281,7 @@
(λ [(Ref String a)] ())
</p>
<span>
</span>
<p class="doc">
<p>prints a string ref to stderr, does not append a newline.</p>
@ -291,7 +301,7 @@
(λ [(Ref String a)] ())
</p>
<span>
</span>
<p class="doc">
<p>prints a string ref to stderr, appends a newline.</p>
@ -311,7 +321,7 @@
(λ [Int] a)
</p>
<span>
</span>
<p class="doc">
<p>exit the current program with a return code.</p>
@ -331,7 +341,7 @@
(λ [(Ptr FILE)] ())
</p>
<span>
</span>
<p class="doc">
<p>closes a file pointer.</p>
@ -351,7 +361,7 @@
(λ [(Ptr FILE)] ())
</p>
<span>
</span>
<p class="doc">
<p>flushes a file pointer (i.e. commits every write).</p>
@ -371,7 +381,7 @@
(λ [(Ptr FILE)] Char)
</p>
<span>
</span>
<p class="doc">
<p>gets a character from a file pointer.</p>
@ -391,10 +401,10 @@
(λ [(Ref String a), (Ref String b)] (Ptr FILE))
</p>
<span>
</span>
<p class="doc">
<p>opens a file by name using a mode (one or multiple of [r]ead, [w]rite, and [a]ppend), returns a file pointer.</p>
<p>opens a file by name using a mode (one or multiple of [r]ead, [w]rite, and [a]ppend), returns a file pointer. Consider using the function open-file instead.</p>
</p>
</div>
@ -411,7 +421,7 @@
(λ [a, Int, Int, (Ptr FILE)] Int)
</p>
<span>
</span>
<p class="doc">
<p>reads from a file pointer into a pointer.</p>
@ -431,7 +441,7 @@
(λ [(Ptr FILE), Int, Int] ())
</p>
<span>
</span>
<p class="doc">
<p>sets the position indicator of a file.</p>
@ -451,7 +461,7 @@
(λ [(Ptr FILE)] Int)
</p>
<span>
</span>
<p class="doc">
<p>gets the position indicator of a file.</p>
@ -471,7 +481,7 @@
(λ [a, Int, Int, (Ptr FILE)] ())
</p>
<span>
</span>
<p class="doc">
<p>writes to a file pointer.</p>
@ -491,7 +501,7 @@
(λ [] Char)
</p>
<span>
</span>
<p class="doc">
<p>gets a character from stdin.</p>
@ -511,13 +521,52 @@
(λ [] String)
</p>
<span>
</span>
<p class="doc">
<p>gets a line from stdin.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#getenv">
<h3 id="getenv">
getenv
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [String] (Maybe String))
</p>
<pre class="args">
(getenv s)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#open-file">
<h3 id="open-file">
open-file
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [&amp;String, &amp;String] (Result (Ptr FILE) Int))
</p>
<pre class="args">
(open-file filename mode)
</pre>
<p class="doc">
<p>opens a file by name using a mode (one or multiple of [r]ead, [w]rite, and [a]ppend), returns a Result type that contains an error string or a file pointer.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#print">
<h3 id="print">
@ -531,7 +580,7 @@
(λ [(Ref String a)] ())
</p>
<span>
</span>
<p class="doc">
<p>prints a string ref to stdout, does not append a newline.</p>
@ -551,7 +600,7 @@
(λ [(Ref String a)] ())
</p>
<span>
</span>
<p class="doc">
<p>prints a string ref to stdout, appends a newline.</p>
@ -568,7 +617,7 @@
defn
</div>
<p class="sig">
(λ [(Ref String a)] (Result String String))
(λ [&amp;String] (Result String Int))
</p>
<pre class="args">
(read-&gt;EOF filename)
@ -591,7 +640,7 @@
(λ [(Ref String a)] String)
</p>
<span>
</span>
<p class="doc">
<p>returns the contents of a file passed as argument as a string.</p>
@ -611,7 +660,7 @@
(λ [(Ptr FILE)] ())
</p>
<span>
</span>
<p class="doc">
<p>rewinds a file pointer (i.e. puts input and output stream to beginning).</p>
@ -631,10 +680,10 @@
(Ptr FILE)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
@ -650,10 +699,10 @@
(Ptr FILE)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
@ -669,10 +718,10 @@
(Ptr FILE)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
@ -688,7 +737,7 @@
(λ [String] ())
</p>
<span>
</span>
<p class="doc">
<p>unlinks a file (i.e. deletes it).</p>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
@ -139,7 +149,7 @@
Maybe
</h1>
<div class="module-description">
</div>
<div class="binder">
<a class="anchor" href="#=">
@ -174,7 +184,7 @@
(λ [a] (Maybe a))
</p>
<span>
</span>
<p class="doc">
<p>creates a <code>Just</code>.</p>
@ -194,7 +204,7 @@
(λ [] (Maybe a))
</p>
<span>
</span>
<p class="doc">
<p>creates a <code>Nothing</code>.</p>
@ -211,7 +221,7 @@
defn
</div>
<p class="sig">
(λ [(Maybe a), ((λ b) [a] c)] (Maybe c))
(λ [(Maybe a), (Ref (λ [a] b))] (Maybe b))
</p>
<pre class="args">
(apply a f)
@ -234,7 +244,7 @@
(λ [(Ref (Maybe a) b)] (Maybe a))
</p>
<span>
</span>
<p class="doc">
<p>copies a <code>(Maybe a)</code>.</p>
@ -254,7 +264,7 @@
(λ [(Maybe a)] ())
</p>
<span>
</span>
<p class="doc">
<p>deletes a <code>(Maybe a)</code>. Should usually not be called manually.</p>
@ -315,7 +325,7 @@
(λ [(Ref (Maybe a) b)] Int)
</p>
<span>
</span>
<p class="doc">
<p>Gets the tag from a <code>Maybe</code>.</p>
@ -398,7 +408,7 @@ a value using <code>zero</code> if a <code>Nothing</code> is passed.</p>
(λ [(Ref (Maybe a) b)] String)
</p>
<span>
</span>
<p class="doc">
<p>stringifies a <code>&quot;Maybe&quot;</code>.</p>
@ -418,7 +428,7 @@ a value using <code>zero</code> if a <code>Nothing</code> is passed.</p>
(λ [(Ref (Maybe a) b)] String)
</p>
<span>
</span>
<p class="doc">
<p>stringifies a <code>&quot;Maybe&quot;</code>.</p>
@ -476,7 +486,7 @@ a value using <code>zero</code> if a <code>Nothing</code> is passed.</p>
defn
</div>
<p class="sig">
(λ [(Ref (Maybe a) b)] (Ptr a))
(λ [(Ref (Maybe a))] (Ptr a))
</p>
<pre class="args">
(unsafe-ptr a)

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

354
docs/core/Pointer.html Normal file
View File

@ -0,0 +1,354 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="carp_style.css">
</head>
<body>
<div class="content">
<div class="logo">
<a href="http://github.com/carp-lang/Carp">
<img src="logo.png">
</a>
<div class="title">
core
</div>
<div class="index">
<ul>
<li>
<a href="Dynamic.html">
Dynamic
</a>
</li>
<li>
<a href="Int.html">
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
</a>
</li>
<li>
<a href="Bool.html">
Bool
</a>
</li>
<li>
<a href="Float.html">
Float
</a>
</li>
<li>
<a href="Double.html">
Double
</a>
</li>
<li>
<a href="Vector2.html">
Vector2
</a>
</li>
<li>
<a href="Vector3.html">
Vector3
</a>
</li>
<li>
<a href="VectorN.html">
VectorN
</a>
</li>
<li>
<a href="Geometry.html">
Geometry
</a>
</li>
<li>
<a href="Statistics.html">
Statistics
</a>
</li>
<li>
<a href="String.html">
String
</a>
</li>
<li>
<a href="Char.html">
Char
</a>
</li>
<li>
<a href="Pattern.html">
Pattern
</a>
</li>
<li>
<a href="Array.html">
Array
</a>
</li>
<li>
<a href="IO.html">
IO
</a>
</li>
<li>
<a href="System.html">
System
</a>
</li>
<li>
<a href="Debug.html">
Debug
</a>
</li>
<li>
<a href="Test.html">
Test
</a>
</li>
<li>
<a href="Bench.html">
Bench
</a>
</li>
<li>
<a href="Map.html">
Map
</a>
</li>
<li>
<a href="Maybe.html">
Maybe
</a>
</li>
<li>
<a href="Result.html">
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
<h1>
Pointer
</h1>
<div class="module-description">
</div>
<div class="binder">
<a class="anchor" href="#add">
<h3 id="add">
add
</h3>
</a>
<div class="description">
template
</div>
<p class="sig">
(λ [(Ptr p), Long] (Ptr p))
</p>
<span>
</span>
<p class="doc">
<p>adds a long integer value to a pointer.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#copy">
<h3 id="copy">
copy
</h3>
</a>
<div class="description">
template
</div>
<p class="sig">
(λ [(Ref (Ptr p))] (Ptr p))
</p>
<span>
</span>
<p class="doc">
<p>copies a pointer <code>p</code>.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#dec">
<h3 id="dec">
dec
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [(Ptr a)] (Ptr a))
</p>
<pre class="args">
(dec a)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#eq">
<h3 id="eq">
eq
</h3>
</a>
<div class="description">
template
</div>
<p class="sig">
(λ [(Ptr p), (Ptr p)] Bool)
</p>
<span>
</span>
<p class="doc">
<p>checks two pointers for equality.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#from-long">
<h3 id="from-long">
from-long
</h3>
</a>
<div class="description">
template
</div>
<p class="sig">
(λ [Long] (Ptr p))
</p>
<span>
</span>
<p class="doc">
<p>converts a long integer to a pointer.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#inc">
<h3 id="inc">
inc
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [(Ptr a)] (Ptr a))
</p>
<pre class="args">
(inc a)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#sub">
<h3 id="sub">
sub
</h3>
</a>
<div class="description">
template
</div>
<p class="sig">
(λ [(Ptr p), Long] (Ptr p))
</p>
<span>
</span>
<p class="doc">
<p>subtracts a long integer value from a pointer.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#to-long">
<h3 id="to-long">
to-long
</h3>
</a>
<div class="description">
template
</div>
<p class="sig">
(λ [(Ptr p)] Long)
</p>
<span>
</span>
<p class="doc">
<p>converts a pointer to a long integer.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#to-ref">
<h3 id="to-ref">
to-ref
</h3>
</a>
<div class="description">
template
</div>
<p class="sig">
(λ [(Ptr p)] &amp;p)
</p>
<span>
</span>
<p class="doc">
<p>converts a pointer to a reference type. The user will have to ensure themselves that this is a safe operation.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#width">
<h3 id="width">
width
</h3>
</a>
<div class="description">
template
</div>
<p class="sig">
(λ [(Ptr p)] Long)
</p>
<span>
</span>
<p class="doc">
<p>gets the byte size of a pointer.</p>
</p>
</div>
</div>
</body>
</html>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
@ -139,7 +149,7 @@
Result
</h1>
<div class="module-description">
</div>
<div class="binder">
<a class="anchor" href="#=">
@ -174,7 +184,7 @@
(λ [a] (Result b a))
</p>
<span>
</span>
<p class="doc">
<p>creates a <code>Error</code>.</p>
@ -194,7 +204,7 @@
(λ [a] (Result a b))
</p>
<span>
</span>
<p class="doc">
<p>creates a <code>Success</code>.</p>
@ -211,7 +221,7 @@
defn
</div>
<p class="sig">
(λ [(Result a b), ((λ c) [a] (Result d b))] (Result d b))
(λ [(Result a b), (Ref (λ [a] (Result c b)))] (Result c b))
</p>
<pre class="args">
(and-then a f)
@ -232,7 +242,7 @@
defn
</div>
<p class="sig">
(λ [(Result a b), ((λ c) [a] d), ((λ c) [b] e)] (Result d e))
(λ [(Result a b), (Ref (λ [a] c)), (Ref (λ [b] d))] (Result c d))
</p>
<pre class="args">
(apply a success-f error-f)
@ -255,7 +265,7 @@
(λ [(Ref (Result a b) c)] (Result a b))
</p>
<span>
</span>
<p class="doc">
<p>copies a <code>(Result a b)</code>.</p>
@ -275,7 +285,7 @@
(λ [(Result a b)] ())
</p>
<span>
</span>
<p class="doc">
<p>deletes a <code>(Result a b)</code>. Should usually not be called manually.</p>
@ -298,7 +308,7 @@
(error? a)
</pre>
<p class="doc">
</p>
</div>
<div class="binder">
@ -354,7 +364,7 @@
(λ [(Ref (Result a b) c)] Int)
</p>
<span>
</span>
<p class="doc">
<p>Gets the tag from a <code>Result</code>.</p>
@ -371,7 +381,7 @@
defn
</div>
<p class="sig">
(λ [(Result a b), ((λ c) [a] d)] (Result d b))
(λ [(Result a b), (Ref (λ [a] c))] (Result c b))
</p>
<pre class="args">
(map a f)
@ -381,6 +391,26 @@
</p>
</div>
<div class="binder">
<a class="anchor" href="#map-error">
<h3 id="map-error">
map-error
</h3>
</a>
<div class="description">
defn
</div>
<p class="sig">
(λ [(Result a b), (Ref (λ [b] c))] (Result a c))
</p>
<pre class="args">
(map-error a f)
</pre>
<p class="doc">
<p>takes a <code>Result</code> and applies a function <code>f</code> to it if it is an <code>Error</code> type, and wraps it back up. In the case that it is a <code>Success</code>, it is returned as is.</p>
</p>
</div>
<div class="binder">
<a class="anchor" href="#or-else">
<h3 id="or-else">
@ -391,7 +421,11 @@
defn
</div>
<p class="sig">
<<<<<<< HEAD
(λ [(Result a b), ((λ c) [b] (Result a d))] (Result a d))
=======
(λ [(Result a b), (Ref (λ [b] (Result a c)))] (Result a c))
>>>>>>> master
</p>
<pre class="args">
(or-else a f)
@ -415,7 +449,7 @@
(λ [(Ref (Result a b) c)] String)
</p>
<span>
</span>
<p class="doc">
<p>stringifies a <code>&quot;Result&quot;</code>.</p>
@ -435,7 +469,7 @@
(λ [(Ref (Result a b) c)] String)
</p>
<span>
</span>
<p class="doc">
<p>stringifies a <code>&quot;Result&quot;</code>.</p>
@ -534,7 +568,11 @@
defn
</div>
<p class="sig">
<<<<<<< HEAD
(λ [(Result a b), ((λ c) [b] a)] a)
=======
(λ [(Result a b), (Ref (λ [b] a))] a)
>>>>>>> master
</p>
<pre class="args">
(unwrap-or-else a f)

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
@ -511,6 +521,25 @@
</p>
</div>
<div class="binder">
<a class="anchor" href="#from-cstr">
<h3 id="from-cstr">
from-cstr
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
(λ [(Ptr Char)] String)
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#hash">
<h3 id="hash">

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>
@ -140,6 +150,329 @@
</h1>
<div class="module-description">
</div>
<div class="binder">
<a class="anchor" href="#EACCES">
<h3 id="EACCES">
EACCES
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#EEXIST">
<h3 id="EEXIST">
EEXIST
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#EINTR">
<h3 id="EINTR">
EINTR
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#EINVAL">
<h3 id="EINVAL">
EINVAL
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#EIO">
<h3 id="EIO">
EIO
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#EISDIR">
<h3 id="EISDIR">
EISDIR
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#ELOOP">
<h3 id="ELOOP">
ELOOP
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#EMFILE">
<h3 id="EMFILE">
EMFILE
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#ENAMETOOLONG">
<h3 id="ENAMETOOLONG">
ENAMETOOLONG
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#ENOENT">
<h3 id="ENOENT">
ENOENT
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#ENOMEM">
<h3 id="ENOMEM">
ENOMEM
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#ENOSPC">
<h3 id="ENOSPC">
ENOSPC
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#ENOSR">
<h3 id="ENOSR">
ENOSR
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#ENOTDIR">
<h3 id="ENOTDIR">
ENOTDIR
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#ENXIO">
<h3 id="ENXIO">
ENXIO
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#EOVERFLOW">
<h3 id="EOVERFLOW">
EOVERFLOW
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#EROFS">
<h3 id="EROFS">
EROFS
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#abort">
@ -160,6 +493,25 @@
</p>
</div>
<div class="binder">
<a class="anchor" href="#errno">
<h3 id="errno">
errno
</h3>
</a>
<div class="description">
external
</div>
<p class="sig">
Int
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#exit">
<h3 id="exit">

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -27,6 +27,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -132,6 +137,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -23,6 +23,11 @@
Int
</a>
</li>
<li>
<a href="Byte.html">
Byte
</a>
</li>
<li>
<a href="Long.html">
Long
@ -128,6 +133,11 @@
Result
</a>
</li>
<li>
<a href="Pointer.html">
Pointer
</a>
</li>
</ul>
</div>
</div>

View File

@ -13,6 +13,7 @@
(save-docs Dynamic
Int
Byte
Long
Bool
Float
@ -34,6 +35,7 @@
Map
Maybe
Result
Pointer
)
(quit)

View File

@ -170,25 +170,6 @@
</p>
</div>
<div class="binder">
<a class="anchor" href="#Windows">
<h3 id="Windows">
Windows
</h3>
</a>
<div class="description">
module
</div>
<p class="sig">
Module
</p>
<span>
</span>
<p class="doc">
</p>
</div>
<div class="binder">
<a class="anchor" href="#bg">
<h3 id="bg">

View File

@ -198,6 +198,15 @@ templateRaw = defineTemplate
(toTemplate "$DECL { return a.data; }")
(\(FuncTy _ [arrayType] _) -> [])
templateUnsafeRaw :: (String, Binder)
templateUnsafeRaw = defineTemplate
(SymPath ["Array"] "unsafe-raw")
(FuncTy [RefTy (StructTy "Array" [VarTy "t"])] (PointerTy (VarTy "t")))
"returns an array `a` as a raw pointer—useful for interacting with C."
(toTemplate "$t* $NAME (Array* a)")
(toTemplate "$DECL { return a->data; }")
(\(FuncTy [RefTy arrayType] _) -> [])
templateAset :: (String, Binder)
templateAset = defineTypeParameterizedTemplate templateCreator path t docs
where path = SymPath ["Array"] "aset"
@ -377,10 +386,20 @@ templateCopyArray = defineTypeParameterizedTemplate templateCreator path t docs
copyTy :: TypeEnv -> Env -> Ty -> [Token]
copyTy typeEnv env (StructTy "Array" [innerType]) =
[ TokC " for(int i = 0; i < a->len; i++) {\n"
, TokC $ " " ++ insideArrayCopying typeEnv env innerType
, TokC " }\n"
]
if isManaged
then
[ TokC " for(int i = 0; i < a->len; i++) {\n"
, TokC $ " " ++ insideArrayCopying typeEnv env innerType
, TokC " }\n"
]
else
[TokC " memcpy(copy.data, a->data, sizeof(", TokTy (VarTy "a") Normal, TokC ") * a->len);\n"]
where isManaged =
case findFunctionForMember typeEnv env "delete"
(typesDeleterFunctionType innerType) ("Inside array.", innerType) of
FunctionFound _ -> True
FunctionNotFound msg -> False
FunctionIgnored -> False
copyTy _ _ _ = []
-- | The "memberCopy" and "memberDeletion" functions in Deftype are very similar!
@ -419,7 +438,7 @@ strTy typeEnv env (StructTy "Array" [innerType]) =
, TokC " String buffer = CARP_MALLOC(size);\n"
, TokC " String bufferPtr = buffer;\n"
, TokC "\n"
, TokC " snprintf(buffer, size, \"[\");\n"
, TokC " sprintf(buffer, \"[\");\n"
, TokC " bufferPtr += 1;\n"
, TokC "\n"
, TokC " for(int i = 0; i < a->len; i++) {\n"
@ -427,7 +446,7 @@ strTy typeEnv env (StructTy "Array" [innerType]) =
, TokC " }\n"
, TokC "\n"
, TokC " if(a->len > 0) { bufferPtr -= 1; }\n"
, TokC " snprintf(bufferPtr, size, \"]\");\n"
, TokC " sprintf(bufferPtr, \"]\");\n"
, TokC " return buffer;\n"
]
strTy _ _ _ = []
@ -460,7 +479,7 @@ insideArrayStr typeEnv env t =
FunctionFound functionFullName ->
let takeAddressOrNot = if isManaged typeEnv t then "&" else ""
in unlines [ " temp = " ++ functionFullName ++ "(" ++ takeAddressOrNot ++ "((" ++ tyToC t ++ "*)a->data)[i]);"
, " snprintf(bufferPtr, size, \"%s \", temp);"
, " sprintf(bufferPtr, \"%s \", temp);"
, " bufferPtr += strlen(temp) + 1;"
, " if(temp) {"
, " CARP_FREE(temp);"

View File

@ -656,7 +656,10 @@ commandCharAt :: CommandCallback
commandCharAt [a, b] =
return $ case (a, b) of
(XObj (Str s) _ _, XObj (Num IntTy n) _ _) ->
Right (XObj (Chr (s !! (round n :: Int))) (Just dummyInfo) (Just IntTy))
let i = (round n :: Int)
in if length s > i
then Right (XObj (Chr (s !! i)) (Just dummyInfo) (Just IntTy))
else Left (EvalError ("Can't call char-at with " ++ pretty a ++ " and " ++ show i ++ ", index too large") (info a))
_ ->
Left (EvalError ("Can't call char-at with " ++ pretty a ++ " and " ++ pretty b) (info a))
@ -811,7 +814,7 @@ commandReadFile :: CommandCallback
commandReadFile [filename] =
case filename of
XObj (Str fname) _ _ -> do
exceptional <- liftIO $ ((try $ slurp fname) :: (IO (Either IOException String)))
exceptional <- liftIO ((try $ slurp fname) :: (IO (Either IOException String)))
case exceptional of
Right contents ->
return (Right (XObj (Str contents) (Just dummyInfo) (Just StringTy)))
@ -823,10 +826,10 @@ commandReadFile [filename] =
commandWriteFile :: CommandCallback
commandWriteFile [filename, contents] =
case filename of
XObj (Str fname) _ _ -> do
XObj (Str fname) _ _ ->
case contents of
XObj (Str s) _ _ -> do
exceptional <- liftIO $ ((try $ writeFile fname s) :: (IO (Either IOException ())))
exceptional <- liftIO ((try $ writeFile fname s) :: (IO (Either IOException ())))
case exceptional of
Right () -> return dynamicNil
Left _ ->

View File

@ -110,7 +110,7 @@ concretizeXObj allowAmbiguityRoot typeEnv rootEnv visitedDefinitions root =
-- Its name will contain the name of the (normal, non-lambda) function it's contained within,
-- plus the identifier of the particular s-expression that defines the lambda.
SymPath path name = rootDefinitionPath
lambdaPath = SymPath path ("_Lambda_" ++ (lambdaToCName name (envFunctionNestingLevel envWithArgs)) ++ "_" ++ show (infoIdentifier ii))
lambdaPath = SymPath path ("_Lambda_" ++ lambdaToCName name (envFunctionNestingLevel envWithArgs) ++ "_" ++ show (infoIdentifier ii))
lambdaNameSymbol = XObj (Sym lambdaPath Symbol) (Just dummyInfo) Nothing
extendedArgs = if null capturedVars
then args
@ -1219,7 +1219,7 @@ manageMemory typeEnv globalEnv root =
case deletersMatchingXObj xobj deleters of
[] -> return (Left (GettingReferenceToUnownedValue xobj))
[_] -> return (return ())
_ -> error "Too many variables with the same name in set."
_ -> error $ "Too many variables with the same name in set (was looking for " ++ pretty xobj ++ " at " ++ prettyInfoFromXObj xobj ++ ")"
else return (return ())
transferOwnership :: XObj -> XObj -> State MemState (Either TypeError ())

View File

@ -311,11 +311,11 @@ tokensForStr typeEnv env typeName memberPairs concreteStructTy =
, " String buffer = CARP_MALLOC(size);"
, " String bufferPtr = buffer;"
, ""
, " snprintf(bufferPtr, size, \"(%s \", \"" ++ typeName ++ "\");"
, " sprintf(bufferPtr, \"(%s \", \"" ++ typeName ++ "\");"
, " bufferPtr += strlen(\"" ++ typeName ++ "\") + 2;\n"
, joinWith "\n" (map (memberPrn typeEnv env) memberPairs)
, " bufferPtr--;"
, " snprintf(bufferPtr, size, \")\");"
, " sprintf(bufferPtr, \")\");"
, " return buffer;"
, "}"]

View File

@ -98,6 +98,7 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo
Arr _ -> visitArray indent xobj
Num IntTy num -> return (show (round num :: Int))
Num LongTy num -> return (show (round num :: Int) ++ "l")
Num ByteTy num -> return (show (round num :: Int))
Num FloatTy num -> return (show num ++ "f")
Num DoubleTy num -> return (show num)
Num _ _ -> error "Can't emit invalid number type."
@ -315,12 +316,7 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo
appendToSrc (addIndent indent' ++ tyToCLambdaFix exprTy ++ " " ++
tempVarToAvoidClash ++ " = " ++ exprVar ++ ";\n")
zipWithM_ (emitCaseMatcher (removeSuffix caseName)) caseMatchers [0..]
caseExprRetVal <- visit indent' caseExpr
when isNotVoid $
appendToSrc (addIndent indent' ++ retVar ++ " = " ++ caseExprRetVal ++ ";\n")
let Just caseLhsInfo' = caseLhsInfo
delete indent' caseLhsInfo'
appendToSrc (addIndent indent ++ "}\n")
emitCaseEnd caseLhsInfo caseExpr
emitCase exprVar isFirst (XObj (Sym firstPath _) caseLhsInfo _, caseExpr) =
-- Single variable
do appendToSrc (addIndent indent)
@ -330,6 +326,8 @@ toC toCMode (Binder meta root) = emitterSrc (execState (visit startingIndent roo
tempVarToAvoidClash ++ " = " ++ exprVar ++ ";\n")
appendToSrc (addIndent indent' ++ tyToCLambdaFix exprTy ++ " " ++
pathToC firstPath ++ " = " ++ tempVarToAvoidClash ++ ";\n") -- Store the whole expr in a variable
emitCaseEnd caseLhsInfo caseExpr
emitCaseEnd caseLhsInfo caseExpr = do
caseExprRetVal <- visit indent' caseExpr
when isNotVoid $
appendToSrc (addIndent indent' ++ retVar ++ " = " ++ caseExprRetVal ++ ";\n")

View File

@ -265,7 +265,7 @@ eval env xobj =
XObj (Sym (SymPath [] "type") _) _ _ : _ ->
return (makeEvalError ctx Nothing ("Invalid args to `type`: " ++ pretty xobj) (info xobj))
[XObj (Sym (SymPath [] "meta-set!") _) _ _, target@(XObj (Sym path @(SymPath _ name) _) _ _), XObj (Str key) _ _, value] -> do
[XObj (Sym (SymPath [] "meta-set!") _) _ _, target@(XObj (Sym path @(SymPath _ name) _) _ _), XObj (Str key) _ _, value] ->
specialCommandMetaSet path key value
XObj (Sym (SymPath [] "meta-set!") _) _ _ : _ ->
return (makeEvalError ctx Nothing ("Invalid args to `meta-set!`: " ++ pretty xobj) (info xobj))
@ -289,6 +289,13 @@ eval env xobj =
XObj (Sym (SymPath [] "use") _) _ _ : _ ->
return (makeEvalError ctx Nothing ("Invalid args to `use`: " ++ pretty xobj) (info xobj))
[XObj (Sym (SymPath [] "defined?") _) _ _, xobj@(XObj (Sym path _) _ _)] ->
case lookupInEnv path env of
Just found -> return (Right trueXObj)
Nothing -> return (Right falseXObj)
XObj (Sym (SymPath [] "defined?") _) _ _ : _ ->
return (makeEvalError ctx Nothing ("Invalid args to `defined?`: " ++ pretty xobj) (info xobj))
XObj With _ _ : xobj@(XObj (Sym path _) _ _) : forms ->
specialCommandWith xobj path forms
XObj With _ _ : _ ->
@ -851,7 +858,7 @@ specialCommandDefmodule xobj moduleName innerExpressions =
ctxAfterModuleAdditions <- liftIO $ foldM folder ctx' innerExpressions
put (popModulePath ctxAfterModuleAdditions)
return dynamicNil -- TODO: propagate errors...
Just (_, Binder existingMeta (XObj (Lst [(XObj DocStub _ _), _]) _ _)) ->
Just (_, Binder existingMeta (XObj (Lst [XObj DocStub _ _, _]) _ _)) ->
defineIt existingMeta
Just (_, Binder _ x) ->
return (makeEvalError ctx Nothing ("Can't redefine '" ++ moduleName ++ "' as module") (info xobj))
@ -1164,11 +1171,13 @@ commandLoad [xobj@(XObj (Str path) i _)] =
cur <- liftIO getCurrentDirectory
pathExists <- liftIO $ doesPathExist fpath
let cleanup = not pathExists
_ <- liftIO $ createDirectoryIfMissing True $ fpath
_ <- liftIO $ createDirectoryIfMissing True fpath
_ <- liftIO $ setCurrentDirectory fpath
(_, txt, _) <- liftIO $ readProcessWithExitCode "git" ["rev-parse", "--abbrev-ref=loose", "HEAD"] ""
if txt == "HEAD\n"
then doGitLoad path fpath
then do
_ <- liftIO $ setCurrentDirectory cur
doGitLoad path fpath
else do
_ <- liftIO $ readProcessWithExitCode "git" ["init"] ""
_ <- liftIO $ readProcessWithExitCode "git" ["remote", "add", "origin", path] ""
@ -1182,8 +1191,7 @@ commandLoad [xobj@(XObj (Str path) i _)] =
_ <- liftIO $ setCurrentDirectory cur
case x1 of
ExitSuccess -> doGitLoad path fpath
ExitFailure _ ->
invalidPathWith ctx path stderr1 cleanup fpath
ExitFailure _ -> invalidPathWith ctx path stderr1 cleanup fpath
doGitLoad path fpath =
let fName = last (splitOn "/" path)
realName' = if ".git" `isSuffixOf` fName

View File

@ -264,6 +264,7 @@ pretty = visit 0
Dict dict -> "{" ++ joinWithSpace (map (visit indent) (concatMap (\(a, b) -> [a, b]) (Map.toList dict))) ++ "}"
Num IntTy num -> show (round num :: Int)
Num LongTy num -> show num ++ "l"
Num ByteTy num -> show num
Num FloatTy num -> show num ++ "f"
Num DoubleTy num -> show num
Num _ _ -> error "Invalid number type."
@ -614,6 +615,7 @@ xobjToTy (XObj (Sym (SymPath _ "Int") _) _ _) = Just IntTy
xobjToTy (XObj (Sym (SymPath _ "Float") _) _ _) = Just FloatTy
xobjToTy (XObj (Sym (SymPath _ "Double") _) _ _) = Just DoubleTy
xobjToTy (XObj (Sym (SymPath _ "Long") _) _ _) = Just LongTy
xobjToTy (XObj (Sym (SymPath _ "Byte") _) _ _) = Just ByteTy
xobjToTy (XObj (Sym (SymPath _ "String") _) _ _) = Just StringTy
xobjToTy (XObj (Sym (SymPath _ "Pattern") _) _ _) = Just PatternTy
xobjToTy (XObj (Sym (SymPath _ "Char") _) _ _) = Just CharTy

View File

@ -58,6 +58,12 @@ integer :: Parsec.Parsec String ParseState XObj
integer = do (i, num) <- maybeSigned
return (XObj (Num IntTy (read num)) i Nothing)
byte :: Parsec.Parsec String ParseState XObj
byte = do (i, num) <- maybeSigned
_ <- Parsec.char 'b'
incColumn 1
return (XObj (Num ByteTy (read num)) i Nothing)
long :: Parsec.Parsec String ParseState XObj
long = do (i, num) <- maybeSigned
_ <- Parsec.char 'l'
@ -67,6 +73,7 @@ long = do (i, num) <- maybeSigned
number :: Parsec.Parsec String ParseState XObj
number = Parsec.try float <|>
Parsec.try floatNoPeriod <|>
Parsec.try byte <|>
Parsec.try double <|>
Parsec.try long <|>
Parsec.try integer

View File

@ -2,11 +2,14 @@ module Path where
import Debug.Trace
import qualified System.Directory as D
import qualified System.FilePath.Posix as FP
import qualified System.FilePath.Windows as FPW
import qualified System.IO as IO
import Util
(</>) :: FilePath -> FilePath -> FilePath
(</>) = (FP.</>)
(</>) = case platform of
Windows -> (FPW.</>)
_ -> (FP.</>)
cachePath :: FilePath -> IO FilePath
cachePath = xdgPath D.XdgCache

View File

@ -31,6 +31,7 @@ arrayModule = Env { envBindings = bindings
, templateEMap
, templateEFilter
, templateRaw
, templateUnsafeRaw
, templateAset
, templateAsetBang
, templateAsetUninitializedBang
@ -52,7 +53,15 @@ pointerModule = Env { envBindings = bindings
, envUseModules = []
, envMode = ExternalEnv
, envFunctionNestingLevel = 0 }
where bindings = Map.fromList [ templatePointerCopy, templatePointerEqual, templatePointerToRef ]
where bindings = Map.fromList [ templatePointerCopy
, templatePointerEqual
, templatePointerToRef
, templatePointerAdd
, templatePointerSub
, templatePointerWidth
, templatePointerToLong
, templatePointerFromLong
]
-- | A template function for copying (= deref:ing) any pointer.
templatePointerCopy :: (String, Binder)
@ -87,6 +96,56 @@ templatePointerToRef = defineTemplate
,"}"])
(const [])
templatePointerAdd = defineTemplate
(SymPath ["Pointer"] "add")
(FuncTy [PointerTy (VarTy "p"), LongTy] (PointerTy (VarTy "p")))
"adds a long integer value to a pointer."
(toTemplate "$p* $NAME ($p *p, long x)")
(toTemplate $ unlines ["$DECL {"
," return p + x;"
,"}"])
(const [])
templatePointerSub = defineTemplate
(SymPath ["Pointer"] "sub")
(FuncTy [PointerTy (VarTy "p"), LongTy] (PointerTy (VarTy "p")))
"subtracts a long integer value from a pointer."
(toTemplate "$p* $NAME ($p *p, long x)")
(toTemplate $ unlines ["$DECL {"
," return p - x;"
,"}"])
(const [])
templatePointerWidth = defineTemplate
(SymPath ["Pointer"] "width")
(FuncTy [PointerTy (VarTy "p")] LongTy)
"gets the byte size of a pointer."
(toTemplate "long $NAME ($p *p)")
(toTemplate $ unlines ["$DECL {"
," return sizeof(*p);"
,"}"])
(const [])
templatePointerToLong = defineTemplate
(SymPath ["Pointer"] "to-long")
(FuncTy [PointerTy (VarTy "p")] LongTy)
"converts a pointer to a long integer."
(toTemplate "long $NAME ($p *p)")
(toTemplate $ unlines ["$DECL {"
," return (long)p;"
,"}"])
(const [])
templatePointerFromLong = defineTemplate
(SymPath ["Pointer"] "from-long")
(FuncTy [LongTy] (PointerTy (VarTy "p")))
"converts a long integer to a pointer."
(toTemplate "$p* $NAME (long p)")
(toTemplate $ unlines ["$DECL {"
," return ($p*)p;"
,"}"])
(const [])
-- | The System module contains functions for various OS related things like timing and process control.
systemModule :: Env
systemModule = Env { envBindings = bindings
@ -97,6 +156,7 @@ systemModule = Env { envBindings = bindings
, envFunctionNestingLevel = 0 }
where bindings = Map.fromList [ templateExit ]
-- | A template function for exiting.
templateExit :: (String, Binder)
templateExit = defineTemplate

View File

@ -17,15 +17,15 @@ memberPrn typeEnv env (memberName, memberTy) =
in case nameOfPolymorphicFunction typeEnv env strFuncType "prn" of
Just strFunctionPath ->
unlines [" temp = " ++ pathToC strFunctionPath ++ "(" ++ maybeTakeAddress ++ "p->" ++ memberName ++ ");"
, " snprintf(bufferPtr, size, \"%s \", temp);"
, " sprintf(bufferPtr, \"%s \", temp);"
, " bufferPtr += strlen(temp) + 1;"
, " if(temp) { CARP_FREE(temp); temp = NULL; }"
]
Nothing ->
if isExternalType typeEnv memberTy
then unlines [ " temp = malloc(11);"
, " snprintf(temp, 11, \"<external>\");"
, " snprintf(bufferPtr, size, \"%s \", temp);"
, " sprintf(temp, \"<external>\");"
, " sprintf(bufferPtr, \"%s \", temp);"
, " bufferPtr += strlen(temp) + 1;"
, " if(temp) { CARP_FREE(temp); temp = NULL; }"
]

View File

@ -200,12 +200,12 @@ strCase typeEnv env concreteStructTy@(StructTy _ typeVariables) theCase =
let (name, tys, correctedTagName) = namesFromCase theCase concreteStructTy
in unlines
[ " if(p->_tag == " ++ correctedTagName ++ ") {"
, " snprintf(bufferPtr, size, \"(%s \", \"" ++ name ++ "\");"
, " sprintf(bufferPtr, \"(%s \", \"" ++ name ++ "\");"
, " bufferPtr += strlen(\"" ++ name ++ "\") + 2;\n"
, joinWith "\n" (map (memberPrn typeEnv env) (zip (map (\anon -> name ++ "." ++ anon)
anonMemberNames) tys))
, " bufferPtr--;"
, " snprintf(bufferPtr, size, \")\");"
, " sprintf(bufferPtr, \")\");"
, " }"
]

View File

@ -16,7 +16,7 @@ import ToTemplate
instanceBinder :: SymPath -> Ty -> Template -> String -> (String, Binder)
instanceBinder path@(SymPath _ name) actualType template docs =
let (x, _) = instantiateTemplate path actualType template
docObj = (XObj (Str docs) (Just dummyInfo) Nothing)
docObj = XObj (Str docs) (Just dummyInfo) Nothing
meta = MetaData (Map.insert "doc" docObj Map.empty)
in (name, Binder meta x)
@ -24,7 +24,7 @@ instanceBinder path@(SymPath _ name) actualType template docs =
instanceBinderWithDeps :: SymPath -> Ty -> Template -> String -> ((String, Binder), [XObj])
instanceBinderWithDeps path@(SymPath _ name) actualType template docs =
let (x, deps) = instantiateTemplate path actualType template
docObj = (XObj (Str docs) (Just dummyInfo) Nothing)
docObj = XObj (Str docs) (Just dummyInfo) Nothing
meta = MetaData (Map.insert "doc" docObj Map.empty)
in ((name, Binder meta x), deps)
@ -45,7 +45,7 @@ defineTemplate path t docs declaration definition depsFunc =
template = Template t (const declaration) (const definition) depsFunc
i = Info 0 0 (show path ++ ".template") Set.empty 0
defLst = [XObj (Deftemplate (TemplateCreator (\_ _ -> template))) Nothing Nothing, XObj (Sym path Symbol) Nothing Nothing]
docObj = (XObj (Str docs) (Just dummyInfo) Nothing)
docObj = XObj (Str docs) (Just dummyInfo) Nothing
meta = MetaData (Map.insert "doc" docObj Map.empty)
in (name, Binder meta (XObj (Lst defLst) (Just i) (Just t)))
@ -55,7 +55,7 @@ defineTypeParameterizedTemplate templateCreator path t docs =
let (SymPath _ name) = path
i = Info 0 0 (show path ++ ".parameterizedTemplate") Set.empty 0
defLst = [XObj (Deftemplate templateCreator) Nothing Nothing, XObj (Sym path Symbol) Nothing Nothing]
docObj = (XObj (Str docs) (Just dummyInfo) Nothing)
docObj = XObj (Str docs) (Just dummyInfo) Nothing
meta = MetaData (Map.insert "doc" docObj Map.empty)
in (name, Binder meta (XObj (Lst defLst) (Just i) (Just t)))

View File

@ -28,6 +28,7 @@ import Util
-- | Carp types.
data Ty = IntTy
| LongTy
| ByteTy
| BoolTy
| FloatTy
| DoubleTy
@ -73,6 +74,7 @@ instance Show Ty where
show FloatTy = "Float"
show DoubleTy = "Double"
show LongTy = "Long"
show ByteTy = "Byte"
show BoolTy = "Bool"
show StringTy = "String"
show PatternTy = "Pattern"
@ -123,6 +125,7 @@ tyToCManglePtr _ BoolTy = "bool"
tyToCManglePtr _ FloatTy = "float"
tyToCManglePtr _ DoubleTy = "double"
tyToCManglePtr _ LongTy = "long"
tyToCManglePtr _ ByteTy = "uint8_t"
tyToCManglePtr _ StringTy = "String"
tyToCManglePtr _ PatternTy = "Pattern"
tyToCManglePtr _ CharTy = "char"

View File

@ -38,6 +38,7 @@ canBeUsedAsMemberType typeEnv typeVariables t xobj =
IntTy -> return ()
FloatTy -> return ()
DoubleTy -> return ()
ByteTy -> return ()
LongTy -> return ()
BoolTy -> return ()
StringTy -> return ()

View File

@ -0,0 +1,2 @@
(Project.config "file-path-print-length" "short")
(String.char-at "" 1)

View File

@ -282,6 +282,14 @@
2
(predicate-count &[1 8 5 10 3] &(fn [i] (Int.even? @i)))
"predicate-count works")
(assert-equal test
&1
(Pointer.to-ref (unsafe-raw &[1 2 3]))
"unsafe-raw works")
(assert-equal test
&2
(Pointer.to-ref (Pointer.inc (unsafe-raw &[1 2 3])))
"unsafe-raw works II")
(assert-equal test
&[1 3 5]
&(remove &2 [2 1 3 2 5])
@ -293,4 +301,9 @@
(assert-equal test
&[1 3]
&(remove-nth 1 [1 2 3])
"remove-nth works"))
"remove-nth works")
(assert-equal test
&[1.0 1.5 2.0 2.5]
&(unreduce 1.0 &(fn [x] (< x 3.0)) &(fn [x] (+ x 0.5)))
"unreduce works")
)

50
test/byte_math.carp Normal file
View File

@ -0,0 +1,50 @@
(load "Test.carp")
(use-all Byte Test)
(deftest test
(assert-equal test
1b
(min 1b 2b)
"min works as expected")
(assert-equal test
2b
(max 1b 2b)
"max works as expected")
(assert-equal test
false
(even? 3b)
"even? works as expected")
(assert-equal test
true
(odd? 3b)
"odd? works as expected")
(assert-equal test
1b
(bit-and 3b 5b)
"bit-and works as expected")
(assert-equal test
5b
(bit-or 1b 4b)
"bit-or works as expected")
(assert-equal test
4b
(bit-xor 1b 5b)
"bit-xor works as expected")
(assert-equal test
1b
(bit-not 254b)
"bit-not works as expected")
(assert-equal test
8b
(bit-shift-left 2b 2b)
"bit-shift-left works as expected")
(assert-equal test
2b
(bit-shift-right 16b 3b)
"bit-shift-right works as expected")
(assert-equal test
1
(/ 3 2)
"integer division truncates as expected")
)

View File

@ -101,4 +101,10 @@
0l
(to-bytes 0.0)
"to-bytes works as expected II"
))
)
(assert-equal test
10.3
(from-string "10.3")
"from-string works as expected"
)
)

View File

@ -2,6 +2,7 @@
# Runs the executable and compares its output to the .expected file
echo $1
./carp.sh $1 --log-memory -x > test/output/$1.output.actual 2>&1
if ! diff test/output/$1.output.actual test/output/$1.output.expected; then

View File

@ -107,4 +107,10 @@
0
(to-bytes 0.0f)
"to-bytes works as expected II"
))
)
(assert-equal test
10.3f
(from-string "10.3")
"from-string works as expected"
)
)

21
test/generics.carp Normal file
View File

@ -0,0 +1,21 @@
(load "Test.carp")
(use Test)
(deftest test
(assert-equal test
1
(id 1)
"id works I"
)
(assert-equal test
&(Maybe.Just 1)
&(id (Maybe.Just 1))
"id works II"
)
(assert-equal test
20
((const 20) 1)
"const works"
)
)

14
test/io.carp Normal file
View File

@ -0,0 +1,14 @@
(load "Test.carp")
(use-all IO Test)
(deftest test
(assert-equal test
&(Maybe.Nothing)
&(IO.getenv @"thisdoesnotexist")
"getenv works on non-existant variable"
)
(assert-true test
(Maybe.just? &(IO.getenv @"PATH"))
"getenv works on existant variable"
)
)

View File

@ -45,12 +45,12 @@
)
(assert-equal test
2
(from (apply (Just 1) Int.inc) 0)
(from (apply (Just 1) &Int.inc) 0)
"apply works on Just"
)
(assert-equal test
0
(from (apply (the (Maybe Int) (Nothing)) Int.inc) 0)
(from (apply (the (Maybe Int) (Nothing)) &Int.inc) 0)
"apply works on Nothing"
)
(assert-equal test

View File

@ -0,0 +1 @@
Can't call char-at with "" and 1, index too large at char_at_index.carp:2:17.

38
test/pointer.carp Normal file
View File

@ -0,0 +1,38 @@
(load "Test.carp")
(use-all Test Pointer)
; we go to the middle of a chunk of 10 safe elements
(def x (add (Array.raw (the (Array Int) (Array.allocate 10))) 5l))
(def xa (to-long x))
(def w (width x))
; these tests are sadly a little unsafe
(deftest test
(assert-equal test
1l
; we assume that the width of a char is 1
(width (Array.raw (the (Array Char) [])))
"Pointer.width works as expected"
)
(assert-equal test
(+ xa (* 3l w))
(to-long (add x 3l))
"Pointer.add works as expected"
)
(assert-equal test
(- xa (* 3l w))
(to-long (sub x 3l))
"Pointer.sub works as expected"
)
(assert-equal test
(+ xa w)
(to-long (inc x))
"Pointer.inc works as expected"
)
(assert-equal test
(- xa w)
(to-long (dec x))
"Pointer.dec works as expected"
)
)

View File

@ -34,7 +34,7 @@
@&Int.MAX
"test that the address of Int.MAX can be taken")
(assert-equal test
&(Result.Error @"File “foobar” couldnt be opened!")
&(Result.Error System.ENOENT)
&(IO.read->EOF "foobar")
"test that reading from an undefined file works")
(assert-equal test

View File

@ -21,31 +21,40 @@
)
(assert-equal test
&(Success 1)
&(apply (Success 0) Int.inc Int.dec)
&(apply (Success 0) &Int.inc &Int.dec)
"apply works with Success"
)
(assert-equal test
&(Error -1)
&(apply (Error 0) Int.inc Int.dec)
&(apply (Error 0) &Int.inc &Int.dec)
"apply works with Error"
)
(assert-true test
(error? &(map (Error @"hi") Int.inc))
(error? &(map (Error @"hi") &Int.inc))
"map works with Error"
)
(assert-equal test
&(Success 2)
&(map (the (Result Int String) (Success 1)) Int.inc)
&(map (the (Result Int String) (Success 1)) &Int.inc)
"map works with Success"
)
(assert-true test
(error? &(and-then (Error @"hi") (fn [x] (Success (Int.inc x)))))
(success? &(map-error (Success @"hi") &Int.inc))
"map-error works with Success"
)
(assert-equal test
&(Error 2)
&(map-error (the (Result String Int) (Error 1)) &Int.inc)
"map-error works with Error"
)
(assert-true test
(error? &(and-then (Error @"hi") &(fn [x] (Success (Int.inc x)))))
"and-then works with Error"
)
(assert-equal test
&(Success 2)
&(and-then (the (Result Int String) (Success 1))
(fn [x] (Success (Int.inc x))))
&(fn [x] (Success (Int.inc x))))
"and-then works with Success"
)
(assert-equal test
@ -61,23 +70,23 @@
(assert-equal test
&(Error 5)
&(or-else (the (Result Int String) (Error @"error"))
(fn [x] (Error (String.length &x))))
&(fn [x] (Error (String.length &x))))
"or-else works with Error"
)
(assert-equal test
&(Success 1)
&(or-else (Success 1) (fn [x] (Error (String.length &x))))
&(or-else (Success 1) &(fn [x] (Error (String.length &x))))
"or-else works with Success"
)
(assert-equal test
5
(unwrap-or-else (the (Result Int String) (Error @"error"))
(fn [s] (String.length &s)))
&(fn [s] (String.length &s)))
"unwrap-or-else works with Error"
)
(assert-equal test
1
(unwrap-or-else (Success 1) (fn [s] (String.length &s)))
(unwrap-or-else (Success 1) &(fn [s] (String.length &s)))
"unwrap-or-else works with Success"
)
(assert-equal test

19
test/system.carp Normal file
View File

@ -0,0 +1,19 @@
(load "Test.carp")
(use-all Test IO Result)
(defn open-existing-file? [filename]
(let [f (open-file filename "r")]
(match f
(Error _) false
(Success x) (do
(fclose x)
true))))
(deftest test
(assert-true test
(error? &(open-file "asfasdfafs.txt" "r"))
"An error is given when the file doesn't exist")
(assert-true test
(open-existing-file? "test/system.carp")
"files that exist are opened properly"))