Fixed build on Linux. Use CMake to find libffi. Removed implementation code from header files. Fixed a few compiler warnings.

This commit is contained in:
Jeremiah LaRocco 2016-06-09 00:05:25 -06:00
parent 5fa516407a
commit b3c486b1bf
13 changed files with 531 additions and 794 deletions

4
.gitignore vendored
View File

@ -1,6 +1,10 @@
*.dSYM
a.out
CMakeCache.txt
CMakeFiles
cmake_install.cmake
Makefile
.DS_Store

View File

@ -7,29 +7,26 @@ set(VERSION_MINOR "0")
set(VERSION_PATCH "1")
set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
set(LIBFFI_INCLUDE_PATH
"${PROJECT_SOURCE_DIR}/../libffi/x86_64-apple-darwin15.3.0/include"
CACHE
PATH
"libffi include directory")
set(LIBFFI_LIBRARY_PATH
"${PROJECT_SOURCE_DIR}/../libffi/x86_64-apple-darwin15.3.0/.libs"
CACHE
PATH
"libffi library directory")
set(SOURCE_DIR src)
include(globfiles.cmake)
include_directories(${LIBFFI_INCLUDE_PATH})
link_directories(${LIBFFI_LIBRARY_PATH})
find_package(Threads)
find_library(M_LIB m)
find_package(PkgConfig)
pkg_check_modules(LIBFFI libffi)
mark_as_advanced(LIBFFI_INCLUDE_DIR LIBFFI_LIBRARIES )
include_directories(shared ${LIBFFI_INCLUDE_DIR})
add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_h} ${${PROJECT_NAME}_c})
target_link_libraries(${PROJECT_NAME} ffi)
target_link_libraries(${PROJECT_NAME} ${LIBFFI_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${M_LIB} ${CMAKE_DL_LIBS})
set_target_properties(${PROJECT_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")

628
Makefile
View File

@ -1,628 +0,0 @@
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.5
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E remove -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/jeremiah/src/Carp
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/jeremiah/src/Carp
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target rebuild_cache
rebuild_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
/usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# Special rule for the target edit_cache
edit_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..."
/usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /home/jeremiah/src/Carp/CMakeFiles /home/jeremiah/src/Carp/CMakeFiles/progress.marks
$(MAKE) -f CMakeFiles/Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start /home/jeremiah/src/Carp/CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles/Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named carp-repl
# Build rule for target.
carp-repl: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 carp-repl
.PHONY : carp-repl
# fast build rule for target.
carp-repl/fast:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/build
.PHONY : carp-repl/fast
src/bytecode.o: src/bytecode.c.o
.PHONY : src/bytecode.o
# target to build an object file
src/bytecode.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/bytecode.c.o
.PHONY : src/bytecode.c.o
src/bytecode.i: src/bytecode.c.i
.PHONY : src/bytecode.i
# target to preprocess a source file
src/bytecode.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/bytecode.c.i
.PHONY : src/bytecode.c.i
src/bytecode.s: src/bytecode.c.s
.PHONY : src/bytecode.s
# target to generate assembly for a file
src/bytecode.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/bytecode.c.s
.PHONY : src/bytecode.c.s
src/call_ffi.o: src/call_ffi.c.o
.PHONY : src/call_ffi.o
# target to build an object file
src/call_ffi.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/call_ffi.c.o
.PHONY : src/call_ffi.c.o
src/call_ffi.i: src/call_ffi.c.i
.PHONY : src/call_ffi.i
# target to preprocess a source file
src/call_ffi.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/call_ffi.c.i
.PHONY : src/call_ffi.c.i
src/call_ffi.s: src/call_ffi.c.s
.PHONY : src/call_ffi.s
# target to generate assembly for a file
src/call_ffi.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/call_ffi.c.s
.PHONY : src/call_ffi.c.s
src/env.o: src/env.c.o
.PHONY : src/env.o
# target to build an object file
src/env.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/env.c.o
.PHONY : src/env.c.o
src/env.i: src/env.c.i
.PHONY : src/env.i
# target to preprocess a source file
src/env.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/env.c.i
.PHONY : src/env.c.i
src/env.s: src/env.c.s
.PHONY : src/env.s
# target to generate assembly for a file
src/env.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/env.c.s
.PHONY : src/env.c.s
src/eval.o: src/eval.c.o
.PHONY : src/eval.o
# target to build an object file
src/eval.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/eval.c.o
.PHONY : src/eval.c.o
src/eval.i: src/eval.c.i
.PHONY : src/eval.i
# target to preprocess a source file
src/eval.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/eval.c.i
.PHONY : src/eval.c.i
src/eval.s: src/eval.c.s
.PHONY : src/eval.s
# target to generate assembly for a file
src/eval.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/eval.c.s
.PHONY : src/eval.c.s
src/gc.o: src/gc.c.o
.PHONY : src/gc.o
# target to build an object file
src/gc.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/gc.c.o
.PHONY : src/gc.c.o
src/gc.i: src/gc.c.i
.PHONY : src/gc.i
# target to preprocess a source file
src/gc.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/gc.c.i
.PHONY : src/gc.c.i
src/gc.s: src/gc.c.s
.PHONY : src/gc.s
# target to generate assembly for a file
src/gc.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/gc.c.s
.PHONY : src/gc.c.s
src/main.o: src/main.c.o
.PHONY : src/main.o
# target to build an object file
src/main.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/main.c.o
.PHONY : src/main.c.o
src/main.i: src/main.c.i
.PHONY : src/main.i
# target to preprocess a source file
src/main.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/main.c.i
.PHONY : src/main.c.i
src/main.s: src/main.c.s
.PHONY : src/main.s
# target to generate assembly for a file
src/main.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/main.c.s
.PHONY : src/main.c.s
src/match.o: src/match.c.o
.PHONY : src/match.o
# target to build an object file
src/match.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/match.c.o
.PHONY : src/match.c.o
src/match.i: src/match.c.i
.PHONY : src/match.i
# target to preprocess a source file
src/match.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/match.c.i
.PHONY : src/match.c.i
src/match.s: src/match.c.s
.PHONY : src/match.s
# target to generate assembly for a file
src/match.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/match.c.s
.PHONY : src/match.c.s
src/obj.o: src/obj.c.o
.PHONY : src/obj.o
# target to build an object file
src/obj.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj.c.o
.PHONY : src/obj.c.o
src/obj.i: src/obj.c.i
.PHONY : src/obj.i
# target to preprocess a source file
src/obj.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj.c.i
.PHONY : src/obj.c.i
src/obj.s: src/obj.c.s
.PHONY : src/obj.s
# target to generate assembly for a file
src/obj.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj.c.s
.PHONY : src/obj.c.s
src/obj_array.o: src/obj_array.c.o
.PHONY : src/obj_array.o
# target to build an object file
src/obj_array.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj_array.c.o
.PHONY : src/obj_array.c.o
src/obj_array.i: src/obj_array.c.i
.PHONY : src/obj_array.i
# target to preprocess a source file
src/obj_array.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj_array.c.i
.PHONY : src/obj_array.c.i
src/obj_array.s: src/obj_array.c.s
.PHONY : src/obj_array.s
# target to generate assembly for a file
src/obj_array.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj_array.c.s
.PHONY : src/obj_array.c.s
src/obj_conversions.o: src/obj_conversions.c.o
.PHONY : src/obj_conversions.o
# target to build an object file
src/obj_conversions.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj_conversions.c.o
.PHONY : src/obj_conversions.c.o
src/obj_conversions.i: src/obj_conversions.c.i
.PHONY : src/obj_conversions.i
# target to preprocess a source file
src/obj_conversions.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj_conversions.c.i
.PHONY : src/obj_conversions.c.i
src/obj_conversions.s: src/obj_conversions.c.s
.PHONY : src/obj_conversions.s
# target to generate assembly for a file
src/obj_conversions.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj_conversions.c.s
.PHONY : src/obj_conversions.c.s
src/obj_string.o: src/obj_string.c.o
.PHONY : src/obj_string.o
# target to build an object file
src/obj_string.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj_string.c.o
.PHONY : src/obj_string.c.o
src/obj_string.i: src/obj_string.c.i
.PHONY : src/obj_string.i
# target to preprocess a source file
src/obj_string.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj_string.c.i
.PHONY : src/obj_string.c.i
src/obj_string.s: src/obj_string.c.s
.PHONY : src/obj_string.s
# target to generate assembly for a file
src/obj_string.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/obj_string.c.s
.PHONY : src/obj_string.c.s
src/primops.o: src/primops.c.o
.PHONY : src/primops.o
# target to build an object file
src/primops.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/primops.c.o
.PHONY : src/primops.c.o
src/primops.i: src/primops.c.i
.PHONY : src/primops.i
# target to preprocess a source file
src/primops.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/primops.c.i
.PHONY : src/primops.c.i
src/primops.s: src/primops.c.s
.PHONY : src/primops.s
# target to generate assembly for a file
src/primops.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/primops.c.s
.PHONY : src/primops.c.s
src/process.o: src/process.c.o
.PHONY : src/process.o
# target to build an object file
src/process.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/process.c.o
.PHONY : src/process.c.o
src/process.i: src/process.c.i
.PHONY : src/process.i
# target to preprocess a source file
src/process.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/process.c.i
.PHONY : src/process.c.i
src/process.s: src/process.c.s
.PHONY : src/process.s
# target to generate assembly for a file
src/process.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/process.c.s
.PHONY : src/process.c.s
src/reader.o: src/reader.c.o
.PHONY : src/reader.o
# target to build an object file
src/reader.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/reader.c.o
.PHONY : src/reader.c.o
src/reader.i: src/reader.c.i
.PHONY : src/reader.i
# target to preprocess a source file
src/reader.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/reader.c.i
.PHONY : src/reader.c.i
src/reader.s: src/reader.c.s
.PHONY : src/reader.s
# target to generate assembly for a file
src/reader.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/reader.c.s
.PHONY : src/reader.c.s
src/repl.o: src/repl.c.o
.PHONY : src/repl.o
# target to build an object file
src/repl.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/repl.c.o
.PHONY : src/repl.c.o
src/repl.i: src/repl.c.i
.PHONY : src/repl.i
# target to preprocess a source file
src/repl.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/repl.c.i
.PHONY : src/repl.c.i
src/repl.s: src/repl.c.s
.PHONY : src/repl.s
# target to generate assembly for a file
src/repl.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/repl.c.s
.PHONY : src/repl.c.s
src/unify.o: src/unify.c.o
.PHONY : src/unify.o
# target to build an object file
src/unify.c.o:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/unify.c.o
.PHONY : src/unify.c.o
src/unify.i: src/unify.c.i
.PHONY : src/unify.i
# target to preprocess a source file
src/unify.c.i:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/unify.c.i
.PHONY : src/unify.c.i
src/unify.s: src/unify.c.s
.PHONY : src/unify.s
# target to generate assembly for a file
src/unify.c.s:
$(MAKE) -f CMakeFiles/carp-repl.dir/build.make CMakeFiles/carp-repl.dir/src/unify.c.s
.PHONY : src/unify.c.s
# Help Target
help:
@echo "The following are some of the valid targets for this Makefile:"
@echo "... all (the default if no target is provided)"
@echo "... clean"
@echo "... depend"
@echo "... rebuild_cache"
@echo "... edit_cache"
@echo "... carp-repl"
@echo "... src/bytecode.o"
@echo "... src/bytecode.i"
@echo "... src/bytecode.s"
@echo "... src/call_ffi.o"
@echo "... src/call_ffi.i"
@echo "... src/call_ffi.s"
@echo "... src/env.o"
@echo "... src/env.i"
@echo "... src/env.s"
@echo "... src/eval.o"
@echo "... src/eval.i"
@echo "... src/eval.s"
@echo "... src/gc.o"
@echo "... src/gc.i"
@echo "... src/gc.s"
@echo "... src/main.o"
@echo "... src/main.i"
@echo "... src/main.s"
@echo "... src/match.o"
@echo "... src/match.i"
@echo "... src/match.s"
@echo "... src/obj.o"
@echo "... src/obj.i"
@echo "... src/obj.s"
@echo "... src/obj_array.o"
@echo "... src/obj_array.i"
@echo "... src/obj_array.s"
@echo "... src/obj_conversions.o"
@echo "... src/obj_conversions.i"
@echo "... src/obj_conversions.s"
@echo "... src/obj_string.o"
@echo "... src/obj_string.i"
@echo "... src/obj_string.s"
@echo "... src/primops.o"
@echo "... src/primops.i"
@echo "... src/primops.s"
@echo "... src/process.o"
@echo "... src/process.i"
@echo "... src/process.s"
@echo "... src/reader.o"
@echo "... src/reader.i"
@echo "... src/reader.s"
@echo "... src/repl.o"
@echo "... src/repl.i"
@echo "... src/repl.s"
@echo "... src/unify.o"
@echo "... src/unify.i"
@echo "... src/unify.s"
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system

View File

@ -1,13 +1,8 @@
#pragma once
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stddef.h>
#include <signal.h>
#ifndef CARP_SHARED_H
#define CARP_SHARED_H
#include "types.h"
#include "platform.h"
@ -25,167 +20,63 @@ typedef void* any;
typedef char* string;
EXPORT int intsqrt(int x) { return (int)sqrt(x); }
EXPORT float itof(int x) { return (float)x; }
EXPORT float dtof(double x) { return (float)x; }
EXPORT double ftod(float x) { return (double)x; }
EXPORT int intsqrt(int x);
EXPORT float itof(int x);
EXPORT float dtof(double x);
EXPORT double ftod(float x);
#ifdef max
#undef max
#endif
EXPORT int max(int x, int y) {
return x > y ? x : y;
}
EXPORT int max(int x, int y);
EXPORT string itos(int x) {
char *s = malloc(sizeof(char) * 32);
snprintf(s, 32, "%d", x);
return s;
}
EXPORT string itos(int x);
EXPORT bool nullQMARK(void *p) {
return p == NULL;
}
EXPORT bool nullQMARK(void *p);
EXPORT bool not(bool x) {
return !x;
}
EXPORT bool not(bool x);
EXPORT void print(string msg) {
printf("%s", msg);
}
EXPORT void print(string msg);
EXPORT void println(string msg) {
assert(msg);
printf("%s\n", msg);
}
EXPORT void println(string msg);
// This function is used for testing of the ownership system
EXPORT void eat_string(char *s) {
free(s);
}
EXPORT void eat_string(char *s);
EXPORT char *string_copy(char *s) {
return strdup(s);
}
EXPORT char *string_copy(char *s);
EXPORT char *string_append(char *s1, char *s2) {
char *new_str = malloc(strlen(s1) + strlen(s2) + 1);
new_str[0] = '\0';
strcat(new_str, s1);
strcat(new_str, s2);
return new_str;
}
EXPORT char *string_append(char *s1, char *s2);
EXPORT bool file_existsQMARK(char *filename) {
FILE *f = fopen(filename, "r");
bool result = f != NULL;
if(result) {
fclose(f);
}
return result;
}
EXPORT bool file_existsQMARK(char *filename);
EXPORT int inc(int x) { return x + 1; }
EXPORT int dec(int x) { return x - 1; }
EXPORT int inc(int x);
EXPORT int dec(int x);
EXPORT void async(void *f) {
//printf("Async starting.\n");
carp_thread_t th = carp_thread_create(f, "Async");
carp_thread_destroy(th);
//printf("Async done.\n");
}
EXPORT void async(void *f);
EXPORT int last_index_of(string s, char c) {
int len = (int)strlen(s);
for(int i = len - 1; i >= 0; i--) {
if(s[i] == c) {
return i;
}
}
return -1;
}
EXPORT int last_index_of(string s, char c);
EXPORT string substring(string s, int index) {
if(index >= strlen(s)) {
printf("Substring out of bounds.\n");
exit(-1);
}
const char *sub = s + index;
return strdup(sub);
}
EXPORT string substring(string s, int index);
EXPORT string file_path_component(string s) {
int i = last_index_of(s, '/');
return substring(s, i + 1);
}
EXPORT string file_path_component(string s);
EXPORT string get_input() {
char in[1024];
fgets(in, 1024, stdin);
return strdup(in);
}
EXPORT string get_input();
EXPORT int mod(int x, int y) {
return x % y;
}
EXPORT int mod(int x, int y);
#ifdef WIN32
EXPORT void sleep(int millis) {
carp_sleep(millis);
}
EXPORT void sleep(int millis);
#endif
EXPORT CARP_PLATFORM platform() {
return carp_get_platform();
}
EXPORT CARP_PLATFORM platform();
EXPORT string get_normal_console_color() {
#ifdef WIN32
return strdup("");
#else
return strdup("\e[0m");
#endif
}
EXPORT string get_normal_console_color();
EXPORT string get_console_color(int x) {
#ifdef WIN32
return strdup("");
#else
char buffer[16];
snprintf(buffer, 16, "\e[3%dm", x);
return strdup(buffer);
#endif
}
EXPORT string get_console_color(int x);
EXPORT Array *chars(string s) {
Array *a = malloc(sizeof(Array));
a->count = strlen(s);
a->data = strdup(s);
return a;
}
EXPORT Array *chars(string s);
EXPORT string string_join(string separator, Array *array_of_strings);
#endif
EXPORT string string_join(string separator, Array *array_of_strings) {
string *casted = (string*)array_of_strings->data;
int separator_len = strlen(separator);
int total_length = 0;
int count = array_of_strings->count;
for(int i = 0; i < count; i++) {
total_length += strlen(casted[i]);
total_length += separator_len;
}
total_length -= separator_len; // last separator not included
total_length += 1; // room for '\0'
string result = malloc(total_length);
char *pos = result;
for(int i = 0; i < count; i++) {
sprintf(pos, "%s", casted[i]);
pos += strlen(casted[i]);
if(i < count - 1) {
sprintf(pos, "%s", separator);
}
pos += separator_len;
}
*pos = '\0';
return result;
}

View File

@ -1,5 +1,8 @@
#pragma once
#ifndef CARP_TYPES_H
#define CARP_TYPES_H
#ifdef bool
#undef bool
#endif
@ -57,3 +60,5 @@ typedef struct {
void *data;
} Array;
#endif

View File

@ -4,7 +4,7 @@
#include "assertions.h"
#include "obj_conversions.h"
#include "primops.h"
#include "../shared/types.h"
#include "types.h"
#define ALLOW_SENDING_LAMBDA_TO_FFI 1
#define LABELED_DISPATCH 0

View File

@ -7,7 +7,7 @@
#include "obj.h"
#include "obj_conversions.h"
#include "constants.h"
#include "../shared/types.h"
#include "types.h"
#include "match.h"
#define LOG_EVAL 0

View File

@ -1,10 +1,12 @@
#include "../shared/platform.h"
#include "../shared/shared.h"
#include "platform.h"
#include "shared.h"
#include "repl.h"
#include "eval.h"
#include "gc.h"
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#define HANDLE_SIGNALS 0

View File

@ -11,7 +11,7 @@
#include <string.h>
#include <assert.h>
#include "constants.h"
#include "../shared/types.h"
#include "types.h"
typedef void (*VoidFn)(void);

View File

@ -1,7 +1,7 @@
#pragma once
#include "obj.h"
#include "../shared/types.h"
#include "types.h"
Obj *primitive_to_obj(Process *process, void *primitive, Obj *return_type);
Obj *primitive_array_to_obj_array(Process *process, Array *carp_array, Obj *inner_type);

View File

@ -14,7 +14,7 @@
#include "gc.h"
#include "obj_conversions.h"
#include "bytecode.h"
#include "../shared/types.h"
#include "types.h"
void register_primop(Process *process, char *name, Primop primop) {
Obj *o = obj_new_primop(primop);

177
src/shared.c Normal file
View File

@ -0,0 +1,177 @@
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stddef.h>
#include <signal.h>
#include "shared.h"
#include "types.h"
#include "platform.h"
#define and &&
int intsqrt(int x) { return (int)sqrt(x); }
float itof(int x) { return (float)x; }
float dtof(double x) { return (float)x; }
double ftod(float x) { return (double)x; }
int max(int x, int y) {
return x > y ? x : y;
}
string itos(int x) {
char *s = malloc(sizeof(char) * 32);
snprintf(s, 32, "%d", x);
return s;
}
bool nullQMARK(void *p) {
return p == NULL;
}
bool not(bool x) {
return !x;
}
void print(string msg) {
printf("%s", msg);
}
void println(string msg) {
assert(msg);
printf("%s\n", msg);
}
// This function is used for testing of the ownership system
void eat_string(char *s) {
free(s);
}
char *string_copy(char *s) {
return strdup(s);
}
char *string_append(char *s1, char *s2) {
char *new_str = malloc(strlen(s1) + strlen(s2) + 1);
new_str[0] = '\0';
strcat(new_str, s1);
strcat(new_str, s2);
return new_str;
}
bool file_existsQMARK(char *filename) {
FILE *f = fopen(filename, "r");
bool result = f != NULL;
if(result) {
fclose(f);
}
return result;
}
int inc(int x) { return x + 1; }
int dec(int x) { return x - 1; }
void async(void *f) {
//printf("Async starting.\n");
carp_thread_t th = carp_thread_create(f, "Async");
carp_thread_destroy(th);
//printf("Async done.\n");
}
int last_index_of(string s, char c) {
int len = (int)strlen(s);
for(int i = len - 1; i >= 0; i--) {
if(s[i] == c) {
return i;
}
}
return -1;
}
string substring(string s, int index) {
if(index >= strlen(s)) {
printf("Substring out of bounds.\n");
exit(-1);
}
const char *sub = s + index;
return strdup(sub);
}
string file_path_component(string s) {
int i = last_index_of(s, '/');
return substring(s, i + 1);
}
string get_input() {
char in[1024];
fgets(in, 1024, stdin);
return strdup(in);
}
int mod(int x, int y) {
return x % y;
}
#ifdef WIN32
void sleep(int millis) {
carp_sleep(millis);
}
#endif
CARP_PLATFORM platform() {
return carp_get_platform();
}
string get_normal_console_color() {
#ifdef WIN32
return strdup("");
#else
return strdup("\e[0m");
#endif
}
string get_console_color(int x) {
#ifdef WIN32
return strdup("");
#else
char buffer[16];
snprintf(buffer, 16, "\e[3%dm", x);
return strdup(buffer);
#endif
}
Array *chars(string s) {
Array *a = malloc(sizeof(Array));
a->count = strlen(s);
a->data = strdup(s);
return a;
}
string string_join(string separator, Array *array_of_strings) {
string *casted = (string*)array_of_strings->data;
int separator_len = strlen(separator);
int total_length = 0;
int count = array_of_strings->count;
for(int i = 0; i < count; i++) {
total_length += strlen(casted[i]);
total_length += separator_len;
}
total_length -= separator_len; // last separator not included
total_length += 1; // room for '\0'
string result = malloc(total_length);
char *pos = result;
for(int i = 0; i < count; i++) {
sprintf(pos, "%s", casted[i]);
pos += strlen(casted[i]);
if(i < count - 1) {
sprintf(pos, "%s", separator);
}
pos += separator_len;
}
*pos = '\0';
return result;
}

289
src/types.c Normal file
View File

@ -0,0 +1,289 @@
#include "types.h"
#if defined(__APPLE__) || defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION)
#ifdef __linux__
#define _GNU_SOURCE
#endif
#include <stdlib.h>
#include <assert.h>
#include <pthread.h>
#include <sys/time.h>
#include <dlfcn.h>
#include <unistd.h>
/* Init/shutdown */
void carp_platform_init() {
}
void carp_platform_shutdown() {
}
/* --- Threads --- */
struct carp_thread {
pthread_t thread;
};
typedef struct thread_arg_wrapper {
carp_thread_routine tr;
void* arg;
} thread_arg_wrapper;
void* thread_proc_wrapper(void* arg) {
thread_arg_wrapper* argw = (thread_arg_wrapper*)arg;
argw->tr(argw->arg);
free(argw);
return 0;
}
carp_thread_t carp_thread_create(carp_thread_routine thread_routine, void* arg) {
carp_thread_t thread = malloc(sizeof(struct carp_thread));
assert(thread);
thread_arg_wrapper* argw = malloc(sizeof(thread_arg_wrapper));
assert(argw);
argw->arg = arg;
argw->tr = thread_routine;
pthread_create(&thread->thread, NULL, thread_proc_wrapper, argw);
return thread;
}
void carp_thread_destroy(carp_thread_t thread) {
free(thread);
}
/* --- Timing --- */
int carp_millitime() {
struct timeval te;
gettimeofday(&te, NULL); // get current time
long long milliseconds = te.tv_sec * 1000LL + te.tv_usec / 1000; // calculate milliseconds
return milliseconds;
}
/* --- Libraries --- */
struct carp_library {
void* handle;
};
carp_library_t carp_load_library(const char* name) {
void* handle = dlopen(name, RTLD_LAZY);
if (handle == NULL) {
return NULL;
}
return (carp_library_t)handle;
}
int carp_unload_library(carp_library_t lib) {
return dlclose((void*)lib);
}
void* carp_find_symbol(carp_library_t lib, const char * name) {
if (lib != NULL) {
return dlsym((void*)lib, name);
}
return dlsym(RTLD_DEFAULT, name);
}
char* carp_get_load_library_error() {
return dlerror();
}
CARP_PLATFORM carp_get_platform() {
return CARP_PLATFORM_OSX;
}
#elif WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <assert.h>
#include <stdlib.h>
/* Support code for library symbol search */
typedef struct module_list {
HMODULE module;
struct module_list* next;
}*module_list_t;
LARGE_INTEGER carp_perf_freq;
HMODULE carp_main_module = INVALID_HANDLE_VALUE;
HMODULE carp_msvcrt_module = INVALID_HANDLE_VALUE;
module_list_t carp_loaded_modules = NULL;
module_list_t new_module_list_node() {
module_list_t lst = malloc(sizeof(struct module_list));
lst->module = INVALID_HANDLE_VALUE;
lst->next = NULL;
return lst;
}
void add_module_to_list(module_list_t lst, HMODULE module) {
while (lst->module != INVALID_HANDLE_VALUE) {
if (lst->next == NULL) {
lst->next = new_module_list_node();
}
lst = lst->next;
}
lst->module = module;
}
void remove_module_from_list(module_list_t lst, HMODULE module) {
while (lst->module != module) {
if (lst->next == NULL) {
return; // not found
}
lst = lst->next;
}
lst->module = INVALID_HANDLE_VALUE;
}
void free_all_modules_and_destroy_module_list(module_list_t lst) {
while (lst) {
if (lst->module != INVALID_HANDLE_VALUE) {
FreeLibrary(lst->module);
}
module_list_t tmp = lst;
lst = lst->next;
free(tmp);
}
}
/* Init/shutdown */
void carp_platform_init() {
QueryPerformanceFrequency(&carp_perf_freq);
carp_main_module = GetModuleHandle(NULL);
carp_msvcrt_module = LoadLibrary("msvcrt.dll");
carp_loaded_modules = new_module_list_node();
add_module_to_list(carp_loaded_modules, carp_msvcrt_module);
}
void carp_platform_shutdown() {
free_all_modules_and_destroy_module_list(carp_loaded_modules);
carp_main_module = INVALID_HANDLE_VALUE;
carp_msvcrt_module = INVALID_HANDLE_VALUE;
carp_loaded_modules = NULL;
}
/* --- Threads --- */
struct carp_thread {
HANDLE handle;
};
typedef struct thread_arg_wrapper {
carp_thread_routine tr;
void* arg;
} thread_arg_wrapper;
DWORD WINAPI thread_proc_wrapper(LPVOID p) {
thread_arg_wrapper* argw = (thread_arg_wrapper*)p;
argw->tr(argw->arg);
free(argw);
return 0;
}
carp_thread_t carp_thread_create(carp_thread_routine thread_routine, void* arg) {
carp_thread_t thread = malloc(sizeof(struct carp_thread));
assert(thread);
thread_arg_wrapper* argw = malloc(sizeof(thread_arg_wrapper));
assert(argw);
argw->arg = arg;
argw->tr = thread_routine;
thread->handle = CreateThread(NULL, 0, thread_proc_wrapper, argw, 0, 0);
return thread;
}
void carp_thread_destroy(carp_thread_t thread) {
CloseHandle(thread->handle);
free(thread);
}
/* --- Timing --- */
int carp_millitime() {
LARGE_INTEGER pt;
QueryPerformanceCounter(&pt);
return (int)(((double)pt.QuadPart) / ((double)carp_perf_freq.QuadPart) * 1000);
}
/* --- Libraries --- */
struct carp_library {
HMODULE module;
};
carp_library_t carp_load_library(const char* name) {
HMODULE module = LoadLibrary(name);
if (module == NULL) {
return NULL;
}
SetLastError(0);
add_module_to_list(carp_loaded_modules, module);
carp_library_t lib = malloc(sizeof(struct carp_library));
lib->module = module;
return lib;
}
int carp_unload_library(carp_library_t lib) {
remove_module_from_list(carp_loaded_modules, lib->module);
BOOL result = FreeLibrary(lib->module);
free(lib);
return !result;
}
void* carp_find_symbol(carp_library_t lib, const char * name) {
if (lib != NULL) {
assert(lib->module != INVALID_HANDLE_VALUE);
return GetProcAddress(lib->module, name);
}
void* addr = GetProcAddress(carp_main_module, name);
if (addr != NULL) {
return addr;
}
module_list_t lst = carp_loaded_modules;
while (lst) {
if (lst->module != INVALID_HANDLE_VALUE) {
void* addr = GetProcAddress(lst->module, name);
if (addr != NULL) {
return addr;
}
}
lst = lst->next;
}
return NULL;
}
char error_buf[2048];
char* carp_get_load_library_error() {
DWORD error = GetLastError();
if (error == 0) {
return NULL;
}
assert(sizeof(TCHAR) == 1); // If wide chars are used, we have to convert to utf8
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&error_buf,
sizeof(error_buf) - 1,
NULL);
return error_buf;
}
void carp_sleep(int millis) {
Sleep(millis);
}
CARP_PLATFORM carp_get_platform() {
return CARP_PLATFORM_WINDOWS;
}
#endif // WIN32