diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Clean.h | 43 | ||||
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | compile.c | 115 | ||||
-rw-r--r-- | iclean.icl | 93 |
5 files changed, 268 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2fdc4e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +Clean System Files +*.o +iclean @@ -0,0 +1,43 @@ + +#define Clean(a) + +typedef struct clean_string *CleanString; + +/* a string in Clean is: + struct clean_string { + int clean_string_length; + char clean_string_characters[clean_string_length]; + }; + The string does not end with a '\0' ! +*/ + +/* CleanStringLength(clean_string) returns the length of the clean_string in characters */ +#define CleanStringLength(clean_string) (*(unsigned int *)(clean_string)) + +/* CleanStringCharacters(clean_string) returns a pointer to the characters of the clean_string */ +#define CleanStringCharacters(clean_string) ((char*)(1+(unsigned int *)(clean_string))+4) + +/* CleanStringSizeInts(string_length) return size of *CleanString in integers */ +#define CleanStringSizeInts(string_length) (1+(((unsigned int)(string_length)+3)>>2)) + +/* CleanStringVariable(clean_string,string_length) defines variable clean_string with length string_length, + before using the clean_string variable, cast to CleanString, except for the macros above */ +#define CleanStringVariable(clean_string,string_length) unsigned int clean_string[CleanStringSizeInts(string_length)] + +/* CleanStringSizeBytes(string_length) return size of *CleanString in bytes */ +#define CleanStringSizeBytes(string_length) (4+(((unsigned int)(string_length)+3) & -4)) + +typedef int *CleanIntArray; + +/* CleanIntArraySize(clean_array) returns the size (number of elements) of the clean_int_array */ +#define CleanIntArraySize(clean_int_array) (((unsigned int *)(clean_int_array))[-2]) + +typedef double *CleanRealArray; + +/* CleanRealArraySize(clean_real_array) returns the size (number of elements) of the clean_real_array */ +#define CleanRealArraySize(clean_real_array) (((unsigned int *)(clean_real_array))[-2]) + +typedef unsigned char *CleanCharArray; + +/* CleanCharArraySize(clean_char_array) returns the size (number of elements) of the clean_char_array */ +#define CleanCharArraySize(clean_char_array) (((unsigned int *)(clean_char_array))[-1]) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..83ba767 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +all: run + +clean: + rm -rf compile.o iclean "Clean System Files" + +compile.o: compile.c + cc -O0 -c compile.c + +iclean: compile.o iclean.icl + clm -l compile.o iclean -o iclean + +run: iclean + ./iclean + diff --git a/compile.c b/compile.c new file mode 100644 index 0000000..3b92ed2 --- /dev/null +++ b/compile.c @@ -0,0 +1,115 @@ +/** + * Interactive Clean + * + * C functions to compile and run a Clean module + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Camil Staps <info@camilstaps.nl> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include <stdlib.h> +#include <stdio.h> +#include <inttypes.h> +#include <string.h> +#include "Clean.h" + +/** + * Compile a Clean module in a path + * + * This may fail (hard) when out of memory or when clm fails + * clm should be in $PATH + * + * @param CleanString path the path + * @param CleanString module the module + * + * @return void + */ +void compile(CleanString path, CleanString module) { + char* pathchars, * modulechars; + int pathlength, modulelength; + + // Copy from CleanString to normal char[] + pathlength = CleanStringLength(path); + modulelength = CleanStringLength(module); + + pathchars = calloc(sizeof(char), pathlength + 1); + modulechars = calloc(sizeof(char), pathlength + 1); + if (modulechars == NULL || pathchars == NULL) { + printf("Couldn't allocate memory\n"); + exit(-1); + } + + int i; + for (i=0;i<modulelength;i++) + modulechars[i] = CleanStringCharacters(module)[i]; + modulechars[i] = 0x00; + + for (i=0;i<pathlength;i++) + pathchars[i] = CleanStringCharacters(path)[i]; + pathchars[i] = 0x00; + + // cd to <path> + chdir(pathchars); + + // Build command: + // clm -ms <module> -o <module> + char cmd[64] = "clm -ms "; + strcat(cmd, modulechars); + strcat(cmd, " -o "); + strcat(cmd, modulechars); + + // Call clm + system(cmd); +} + +/** + * Run an executable + * + * This may fail when out of memory, or when the executable fails + * The file should be executable by the user + * + * @param CleanString executable the path to the executable + * + * @return void + */ +void run(CleanString executable) { + char* execchars; + int execlength; + + // Copy CleanString to char[] + execlength = CleanStringLength(executable); + + execchars = calloc(sizeof(char), execlength + 1 + 4); + if (execchars == NULL) { + printf("Couldn't allocate memory\n"); + exit(-1); + } + + int i; + for (i=0;i<execlength;i++) + execchars[i] = CleanStringCharacters(executable)[i]; + execchars[i] = 0x00; + + // Build & run command: + // <module> -nt + strcat(execchars, " -nt"); + system(execchars); +} diff --git a/iclean.icl b/iclean.icl new file mode 100644 index 0000000..a5ca38c --- /dev/null +++ b/iclean.icl @@ -0,0 +1,93 @@ +/** + * Interactive Clean + * + * Clean program to easily compile and run one-line Clean expressions + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Camil Staps <info@camilstaps.nl> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +module iclean + +import StdEnv + +// SETTINGS +temp_path :== "/tmp/" +temp_module :== "iclean" +// END SETTINGS + +temp_file :== temp_path +++ temp_module +++ ".icl" + +Start :: *World -> *World +Start w +# w = loop w += w +where + loop :: *World -> *World + loop w + #! w = print "> " w + #! (s,w) = readline w + | s == "" = w + #! w = writemodule s w + #! w = compile temp_path temp_module w + #! w = run (temp_path +++ temp_module) w + = loop w + +print :: String *World -> *World +print s w +# (io,w) = stdio w +# io = fwrites s io +# (ok,w) = fclose io w +| not ok = abort "Couldn't close stdio\n" +| otherwise = w + +readline :: *World -> *(String,*World) +readline w +# (io,w) = stdio w +# (s,io) = freadline io +# (ok,w) = fclose io w +| not ok = abort "Couldn't close stdio\n" +| otherwise = (s % (0,length (l s) - 2), w) +where + l :: String -> [Char] + l s = fromString s + +writemodule :: String *World -> *World +writemodule s w +# (ok,f,w) = fopen temp_file FWriteText w +| not ok = abort ("Couldn't open " +++ temp_file +++ " for writing.\n") +# f = fwrites ("module " +++ temp_module +++ "\n") f +# f = fwrites "import StdEnv\n" f +# f = fwrites ("Start = " +++ s +++ "\n") f +# (ok,w) = fclose f w +| not ok = abort ("Couldn't close " +++ temp_file +++ "\n") +| otherwise = w + +compile :: !String !String *World -> *World +compile _ _ _ = code { + ccall compile "SS:V:p" +} + +run :: !String *World -> *World +run _ _ = code { + ccall run "S:V:p" +} + |