├── nbproject
├── private
│ ├── Makefile-variables.mk
│ ├── private.xml
│ ├── launcher.properties
│ └── configurations.xml
├── project.xml
├── Makefile-variables.mk
├── Package-Debug.bash
├── Package-Release.bash
├── Makefile-Debug.mk
├── Makefile-Release.mk
├── configurations.xml
└── Makefile-impl.mk
├── .gitignore
├── Simplex.h
├── lexer.h
├── README.md
├── environment.h
├── evaluate.h
├── Makefile
├── main.c
├── Standard Library
└── std.sx
├── definitions.h
├── mpc.h
├── built_in.h
└── LICENSE
/nbproject/private/Makefile-variables.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Generated - do not edit!
3 | #
4 | # NOCDDL
5 | #
6 | # Debug configuration
7 | # Release configuration
8 |
--------------------------------------------------------------------------------
/nbproject/private/private.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1
5 | 0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.elf
9 |
10 | # Linker output
11 | *.ilk
12 | *.map
13 | *.exp
14 |
15 | # Precompiled Headers
16 | *.gch
17 | *.pch
18 |
19 | # Libraries
20 | *.lib
21 | *.a
22 | *.la
23 | *.lo
24 |
25 | # Shared objects (inc. Windows DLLs)
26 | *.dll
27 | *.so
28 | *.so.*
29 | *.dylib
30 |
31 | # Executables
32 | *.exe
33 | *.out
34 | *.app
35 | *.i*86
36 | *.x86_64
37 | *.hex
38 |
39 | # Debug files
40 | *.dSYM/
41 | *.su
42 | *.idb
43 | *.pdb
44 |
45 | # Kernel Module Compile Results
46 | *.mod*
47 | *.cmd
48 | .tmp_versions/
49 | modules.order
50 | Module.symvers
51 | Mkfile.old
52 | dkms.conf
53 |
--------------------------------------------------------------------------------
/Simplex.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Mohamed Rashad
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * adouble with this program. If not, see .
16 | */
17 |
18 | /*
19 | * From here, simplex is born.....
20 | *
21 | */
22 |
23 | #ifndef GENERAL_H
24 | #define GENERAL_H
25 |
26 | #include
27 |
28 | #include "definitions.h"
29 | #include "environment.h"
30 | #include "built_in.h"
31 | #include "evaluate.h"
32 | #include "lexer.h"
33 |
34 | #endif /* GENERAL_H */
--------------------------------------------------------------------------------
/nbproject/project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.netbeans.modules.cnd.makeproject
4 |
5 |
6 | Simplex
7 | c
8 |
9 | h
10 | UTF-8
11 |
12 |
13 |
14 |
15 | Debug
16 | 1
17 |
18 |
19 | Release
20 | 1
21 |
22 |
23 |
24 | false
25 |
26 |
27 |
28 | def
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/nbproject/Makefile-variables.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Generated - do not edit!
3 | #
4 | # NOCDDL
5 | #
6 | CND_BASEDIR=`pwd`
7 | CND_BUILDDIR=build
8 | CND_DISTDIR=dist
9 | # Debug configuration
10 | CND_PLATFORM_Debug=GNU-Linux
11 | CND_ARTIFACT_DIR_Debug=dist/Debug/GNU-Linux
12 | CND_ARTIFACT_NAME_Debug=simplex
13 | CND_ARTIFACT_PATH_Debug=dist/Debug/GNU-Linux/simplex
14 | CND_PACKAGE_DIR_Debug=dist/Debug/GNU-Linux/package
15 | CND_PACKAGE_NAME_Debug=simplex.tar
16 | CND_PACKAGE_PATH_Debug=dist/Debug/GNU-Linux/package/simplex.tar
17 | # Release configuration
18 | CND_PLATFORM_Release=GNU-Linux
19 | CND_ARTIFACT_DIR_Release=dist/Release/GNU-Linux
20 | CND_ARTIFACT_NAME_Release=simplex
21 | CND_ARTIFACT_PATH_Release=dist/Release/GNU-Linux/simplex
22 | CND_PACKAGE_DIR_Release=dist/Release/GNU-Linux/package
23 | CND_PACKAGE_NAME_Release=simplex.tar
24 | CND_PACKAGE_PATH_Release=dist/Release/GNU-Linux/package/simplex.tar
25 | #
26 | # include compiler specific variables
27 | #
28 | # dmake command
29 | ROOT:sh = test -f nbproject/private/Makefile-variables.mk || \
30 | (mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk)
31 | #
32 | # gmake command
33 | .PHONY: $(shell test -f nbproject/private/Makefile-variables.mk || (mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk))
34 | #
35 | include nbproject/private/Makefile-variables.mk
36 |
--------------------------------------------------------------------------------
/nbproject/Package-Debug.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash -x
2 |
3 | #
4 | # Generated - do not edit!
5 | #
6 |
7 | # Macros
8 | TOP=`pwd`
9 | CND_PLATFORM=GNU-Linux
10 | CND_CONF=Debug
11 | CND_DISTDIR=dist
12 | CND_BUILDDIR=build
13 | CND_DLIB_EXT=so
14 | NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
15 | TMPDIRNAME=tmp-packaging
16 | OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/simplex
17 | OUTPUT_BASENAME=simplex
18 | PACKAGE_TOP_DIR=simplex/
19 |
20 | # Functions
21 | function checkReturnCode
22 | {
23 | rc=$?
24 | if [ $rc != 0 ]
25 | then
26 | exit $rc
27 | fi
28 | }
29 | function makeDirectory
30 | # $1 directory path
31 | # $2 permission (optional)
32 | {
33 | mkdir -p "$1"
34 | checkReturnCode
35 | if [ "$2" != "" ]
36 | then
37 | chmod $2 "$1"
38 | checkReturnCode
39 | fi
40 | }
41 | function copyFileToTmpDir
42 | # $1 from-file path
43 | # $2 to-file path
44 | # $3 permission
45 | {
46 | cp "$1" "$2"
47 | checkReturnCode
48 | if [ "$3" != "" ]
49 | then
50 | chmod $3 "$2"
51 | checkReturnCode
52 | fi
53 | }
54 |
55 | # Setup
56 | cd "${TOP}"
57 | mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package
58 | rm -rf ${NBTMPDIR}
59 | mkdir -p ${NBTMPDIR}
60 |
61 | # Copy files and create directories and links
62 | cd "${TOP}"
63 | makeDirectory "${NBTMPDIR}/simplex/bin"
64 | copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
65 |
66 |
67 | # Generate tar file
68 | cd "${TOP}"
69 | rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/simplex.tar
70 | cd ${NBTMPDIR}
71 | tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/simplex.tar *
72 | checkReturnCode
73 |
74 | # Cleanup
75 | cd "${TOP}"
76 | rm -rf ${NBTMPDIR}
77 |
--------------------------------------------------------------------------------
/nbproject/Package-Release.bash:
--------------------------------------------------------------------------------
1 | #!/bin/bash -x
2 |
3 | #
4 | # Generated - do not edit!
5 | #
6 |
7 | # Macros
8 | TOP=`pwd`
9 | CND_PLATFORM=GNU-Linux
10 | CND_CONF=Release
11 | CND_DISTDIR=dist
12 | CND_BUILDDIR=build
13 | CND_DLIB_EXT=so
14 | NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
15 | TMPDIRNAME=tmp-packaging
16 | OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/simplex
17 | OUTPUT_BASENAME=simplex
18 | PACKAGE_TOP_DIR=simplex/
19 |
20 | # Functions
21 | function checkReturnCode
22 | {
23 | rc=$?
24 | if [ $rc != 0 ]
25 | then
26 | exit $rc
27 | fi
28 | }
29 | function makeDirectory
30 | # $1 directory path
31 | # $2 permission (optional)
32 | {
33 | mkdir -p "$1"
34 | checkReturnCode
35 | if [ "$2" != "" ]
36 | then
37 | chmod $2 "$1"
38 | checkReturnCode
39 | fi
40 | }
41 | function copyFileToTmpDir
42 | # $1 from-file path
43 | # $2 to-file path
44 | # $3 permission
45 | {
46 | cp "$1" "$2"
47 | checkReturnCode
48 | if [ "$3" != "" ]
49 | then
50 | chmod $3 "$2"
51 | checkReturnCode
52 | fi
53 | }
54 |
55 | # Setup
56 | cd "${TOP}"
57 | mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package
58 | rm -rf ${NBTMPDIR}
59 | mkdir -p ${NBTMPDIR}
60 |
61 | # Copy files and create directories and links
62 | cd "${TOP}"
63 | makeDirectory "${NBTMPDIR}/simplex/bin"
64 | copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
65 |
66 |
67 | # Generate tar file
68 | cd "${TOP}"
69 | rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/simplex.tar
70 | cd ${NBTMPDIR}
71 | tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/simplex.tar *
72 | checkReturnCode
73 |
74 | # Cleanup
75 | cd "${TOP}"
76 | rm -rf ${NBTMPDIR}
77 |
--------------------------------------------------------------------------------
/nbproject/private/launcher.properties:
--------------------------------------------------------------------------------
1 | # Launchers File syntax:
2 | #
3 | # [Must-have property line]
4 | # launcher1.runCommand=
5 | # [Optional extra properties]
6 | # launcher1.displayName=
7 | # launcher1.buildCommand=
8 | # launcher1.runDir=
9 | # launcher1.symbolFiles=
10 | # launcher1.env.=
11 | # (If this value is quoted with ` it is handled as a native command which execution result will become the value)
12 | # [Common launcher properties]
13 | # common.runDir=
14 | # (This value is overwritten by a launcher specific runDir value if the latter exists)
15 | # common.env.=
16 | # (Environment variables from common launcher are merged with launcher specific variables)
17 | # common.symbolFiles=
18 | # (This value is overwritten by a launcher specific symbolFiles value if the latter exists)
19 | #
20 | # In runDir, symbolFiles and env fields you can use these macroses:
21 | # ${PROJECT_DIR} - project directory absolute path
22 | # ${OUTPUT_PATH} - linker output path (relative to project directory path)
23 | # ${OUTPUT_BASENAME}- linker output filename
24 | # ${TESTDIR} - test files directory (relative to project directory path)
25 | # ${OBJECTDIR} - object files directory (relative to project directory path)
26 | # ${CND_DISTDIR} - distribution directory (relative to project directory path)
27 | # ${CND_BUILDDIR} - build directory (relative to project directory path)
28 | # ${CND_PLATFORM} - platform name
29 | # ${CND_CONF} - configuration name
30 | # ${CND_DLIB_EXT} - dynamic library extension
31 | #
32 | # All the project launchers must be listed in the file!
33 | #
34 | # launcher1.runCommand=...
35 | # launcher2.runCommand=...
36 | # ...
37 | # common.runDir=...
38 | # common.env.KEY=VALUE
39 |
40 | # launcher1.runCommand=
--------------------------------------------------------------------------------
/nbproject/Makefile-Debug.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Generated Makefile - do not edit!
3 | #
4 | # Edit the Makefile in the project folder instead (../Makefile). Each target
5 | # has a -pre and a -post target defined where you can add customized code.
6 | #
7 | # This makefile implements configuration specific macros and targets.
8 |
9 |
10 | # Environment
11 | MKDIR=mkdir
12 | CP=cp
13 | GREP=grep
14 | NM=nm
15 | CCADMIN=CCadmin
16 | RANLIB=ranlib
17 | CC=gcc
18 | CCC=g++
19 | CXX=g++
20 | FC=gfortran
21 | AS=as
22 |
23 | # Macros
24 | CND_PLATFORM=GNU-Linux
25 | CND_DLIB_EXT=so
26 | CND_CONF=Debug
27 | CND_DISTDIR=dist
28 | CND_BUILDDIR=build
29 |
30 | # Include project Makefile
31 | include Makefile
32 |
33 | # Object Directory
34 | OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
35 |
36 | # Object Files
37 | OBJECTFILES= \
38 | ${OBJECTDIR}/main.o \
39 | ${OBJECTDIR}/mpc.o
40 |
41 |
42 | # C Compiler Flags
43 | CFLAGS=
44 |
45 | # CC Compiler Flags
46 | CCFLAGS=
47 | CXXFLAGS=
48 |
49 | # Fortran Compiler Flags
50 | FFLAGS=
51 |
52 | # Assembler Flags
53 | ASFLAGS=
54 |
55 | # Link Libraries and Options
56 | LDLIBSOPTIONS=
57 |
58 | # Build Targets
59 | .build-conf: ${BUILD_SUBPROJECTS}
60 | "${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/simplex
61 |
62 | ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/simplex: ${OBJECTFILES}
63 | ${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
64 | ${LINK.c} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/simplex ${OBJECTFILES} ${LDLIBSOPTIONS}
65 |
66 | ${OBJECTDIR}/main.o: main.c
67 | ${MKDIR} -p ${OBJECTDIR}
68 | ${RM} "$@.d"
69 | $(COMPILE.c) -g -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/main.o main.c
70 |
71 | ${OBJECTDIR}/mpc.o: mpc.c
72 | ${MKDIR} -p ${OBJECTDIR}
73 | ${RM} "$@.d"
74 | $(COMPILE.c) -g -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/mpc.o mpc.c
75 |
76 | # Subprojects
77 | .build-subprojects:
78 |
79 | # Clean Targets
80 | .clean-conf: ${CLEAN_SUBPROJECTS}
81 | ${RM} -r ${CND_BUILDDIR}/${CND_CONF}
82 | ${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/simplex
83 |
84 | # Subprojects
85 | .clean-subprojects:
86 |
87 | # Enable dependency checking
88 | .dep.inc: .depcheck-impl
89 |
90 | include .dep.inc
91 |
--------------------------------------------------------------------------------
/nbproject/Makefile-Release.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Generated Makefile - do not edit!
3 | #
4 | # Edit the Makefile in the project folder instead (../Makefile). Each target
5 | # has a -pre and a -post target defined where you can add customized code.
6 | #
7 | # This makefile implements configuration specific macros and targets.
8 |
9 |
10 | # Environment
11 | MKDIR=mkdir
12 | CP=cp
13 | GREP=grep
14 | NM=nm
15 | CCADMIN=CCadmin
16 | RANLIB=ranlib
17 | CC=gcc
18 | CCC=g++
19 | CXX=g++
20 | FC=gfortran
21 | AS=as
22 |
23 | # Macros
24 | CND_PLATFORM=GNU-Linux
25 | CND_DLIB_EXT=so
26 | CND_CONF=Release
27 | CND_DISTDIR=dist
28 | CND_BUILDDIR=build
29 |
30 | # Include project Makefile
31 | include Makefile
32 |
33 | # Object Directory
34 | OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
35 |
36 | # Object Files
37 | OBJECTFILES= \
38 | ${OBJECTDIR}/main.o \
39 | ${OBJECTDIR}/mpc.o
40 |
41 |
42 | # C Compiler Flags
43 | CFLAGS=
44 |
45 | # CC Compiler Flags
46 | CCFLAGS=
47 | CXXFLAGS=
48 |
49 | # Fortran Compiler Flags
50 | FFLAGS=
51 |
52 | # Assembler Flags
53 | ASFLAGS=
54 |
55 | # Link Libraries and Options
56 | LDLIBSOPTIONS=
57 |
58 | # Build Targets
59 | .build-conf: ${BUILD_SUBPROJECTS}
60 | "${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/simplex
61 |
62 | ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/simplex: ${OBJECTFILES}
63 | ${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
64 | ${LINK.c} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/simplex ${OBJECTFILES} ${LDLIBSOPTIONS}
65 |
66 | ${OBJECTDIR}/main.o: main.c
67 | ${MKDIR} -p ${OBJECTDIR}
68 | ${RM} "$@.d"
69 | $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/main.o main.c
70 |
71 | ${OBJECTDIR}/mpc.o: mpc.c
72 | ${MKDIR} -p ${OBJECTDIR}
73 | ${RM} "$@.d"
74 | $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/mpc.o mpc.c
75 |
76 | # Subprojects
77 | .build-subprojects:
78 |
79 | # Clean Targets
80 | .clean-conf: ${CLEAN_SUBPROJECTS}
81 | ${RM} -r ${CND_BUILDDIR}/${CND_CONF}
82 | ${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/simplex
83 |
84 | # Subprojects
85 | .clean-subprojects:
86 |
87 | # Enable dependency checking
88 | .dep.inc: .depcheck-impl
89 |
90 | include .dep.inc
91 |
--------------------------------------------------------------------------------
/lexer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 |
7 | /*
8 | * File: lexer.h
9 | * Author: root
10 | *
11 | * Created on June 15, 2017, 6:54 AM
12 | */
13 |
14 | #ifndef LEXER_H
15 | #define LEXER_H
16 |
17 |
18 | /* Reading */
19 |
20 | smplx_val* smplx_val_read_num(mpc_ast_t* t) {
21 | errno = 0;
22 | double x = atof(t->contents);
23 | return errno != ERANGE ? smplx_val_num(x) : smplx_val_err("Invalid Number.");
24 | }
25 |
26 | smplx_val* smplx_val_read_str(mpc_ast_t* t) {
27 | /* Cut off the final quote character */
28 | t->contents[strlen(t->contents) - 1] = '\0';
29 | /* Copy the string missing out the first quote character */
30 | char* unescaped = malloc(strlen(t->contents + 1) + 1);
31 | strcpy(unescaped, t->contents + 1);
32 | /* Pass through the unescape function */
33 | unescaped = mpcf_unescape(unescaped);
34 | /* Construct a new smplx_val using the string */
35 | smplx_val* str = smplx_val_str(unescaped);
36 | /* Free the string and return */
37 | free(unescaped);
38 | return str;
39 | }
40 |
41 |
42 | /**
43 | *
44 | * Takes the parsed code from mpc and starts evaluating it according to its content
45 | *
46 | * - Number
47 | * - Symbolic Expression
48 | * - Qouted Expression
49 | *
50 | * @param t
51 | * @return
52 | */
53 | smplx_val* smplx_val_read(mpc_ast_t* t) {
54 |
55 | if (strstr(t->tag, "number")) {
56 | return smplx_val_read_num(t);
57 | }
58 | if (strstr(t->tag, "string")) {
59 | return smplx_val_read_str(t);
60 | }
61 | if (strstr(t->tag, "symbol")) {
62 | return smplx_val_sym(t->contents);
63 | }
64 |
65 | smplx_val* x = NULL;
66 | if (strcmp(t->tag, ">") == 0) {
67 | x = smplx_val_sexpr();
68 | }
69 | if (strstr(t->tag, "sexpr")) {
70 | x = smplx_val_sexpr();
71 | }
72 | if (strstr(t->tag, "qexpr")) {
73 | x = smplx_val_qexpr();
74 | }
75 |
76 | for (int i = 0; i < t->children_num; i++) {
77 | if (strcmp(t->children[i]->contents, "(") == 0) {
78 | continue;
79 | }
80 | if (strcmp(t->children[i]->contents, ")") == 0) {
81 | continue;
82 | }
83 | if (strcmp(t->children[i]->contents, "]") == 0) {
84 | continue;
85 | }
86 | if (strcmp(t->children[i]->contents, "[") == 0) {
87 | continue;
88 | }
89 | if (strcmp(t->children[i]->tag, "regex") == 0) {
90 | continue;
91 | }
92 | if (strstr(t->children[i]->tag, "comment")) {
93 | continue;
94 | }
95 | x = smplx_val_add(x, smplx_val_read(t->children[i]));
96 | }
97 |
98 | return x;
99 | }
100 |
101 |
102 | #endif /* LEXER_H */
103 |
104 |
--------------------------------------------------------------------------------
/nbproject/private/configurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Makefile
4 |
5 |
6 |
7 | localhost
8 | 2
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | gdb
24 |
25 |
26 |
27 | "${OUTPUT_PATH} code"
28 | "${OUTPUT_PATH} " code
29 | "${OUTPUT_PATH} "
30 | "${OUTPUT_PATH}" code
31 | "${OUTPUT_PATH}"
32 |
33 | "${OUTPUT_PATH}"
34 |
35 | true
36 | 0
37 | 0
38 |
39 |
40 |
41 |
42 |
43 |
44 | localhost
45 | 2
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | gdb
61 |
62 |
63 |
64 | "${OUTPUT_PATH}"
65 |
66 | "${OUTPUT_PATH}"
67 |
68 | true
69 | 0
70 | 0
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Simplex
2 | Simple Programming Language. Inspired by Lisp programming language.
3 | It's a Lisp for everyone, and no one.
4 |
5 | **[Get Simplex Here](https://github.com/MohammedRashad/Simplex/releases)**
6 |
7 | ## Introduction
8 |
9 |
10 | ### Brief Intro
11 |
12 | Simplex is a Lisp-based programming language (lisp-diaclet or lisp-variant), built for experimentation and educational purposes as a side project, it was meant to be different from the mainstream languages with some amazing features borrowed from many languages.
13 |
14 | The motivation behind it was to push my limits in programming and in **C** especially, also as a part of my learning process to explore computer science and as a personal challenge.
15 |
16 | More detailed documentation and tutorials is being added.
17 |
18 | ### What is simplex ?
19 |
20 | Simplex is simple programming language. Inspired by Lisp, Python, Fortran and BASIC.
21 | With many improvements and modifications, it's my trial to re-invent Lisp.
22 |
23 |
24 |
25 | ## Main Features
26 |
27 | - Functional
28 | - Turing-Complete
29 | - Imperative
30 | - Dynamically-Typed
31 | - Weakly-Typed
32 | - Live Interpreter
33 | - Batch Interpreter
34 | - Implemented in C++
35 |
36 |
37 | ## What's working right now ?
38 |
39 | - Variables
40 | - Scopes
41 | - Live Interpreter
42 | - Functions
43 | - First Order Functions
44 | - Recursion
45 | - Standard Library
46 | - Strings
47 | - Floating Point Numbers
48 | - Logical Operations
49 | - Arithmetic Operations
50 | - Batch Interpreter
51 | - User Input
52 | - Loading Files
53 | - Library Loading
54 | - If Conditional Statements
55 | - Case Statements
56 | - Select Statements
57 | - List operations
58 |
59 | ## Basic Tutorial
60 |
61 | **Printing :**
62 |
63 | (print "Hello World")
64 |
65 | **Input :**
66 |
67 | (scan "x")
68 | **Arithmetic :**
69 |
70 | (+ 3 4 5 6 7) == 25
71 | (- 3 2) == 1
72 | (* 3 4) == 12
73 | (/ 12 6) == 2
74 |
75 | **Variables :**
76 |
77 | (define [a] 100)
78 |
79 | **Lists :**
80 |
81 | (define [w] [1 2 3 4 5 6])
82 |
83 | **Functions :**
84 |
85 | (fun [add x y] [+ x y])
86 |
87 | **Comments:**
88 |
89 | # This is a comment
90 | # Multiline comment
91 |
92 | **Conditonal Statements :**
93 |
94 | # If Statement
95 | if ()
96 | []
97 | []
98 |
99 | # Select Statement
100 | select
101 | [ () ]
102 | [ () ]
103 | [ otherwise () ]
104 |
105 | # Case Statement
106 | case x
107 | [0 "Monday"]
108 | [1 "Tuesday"]
109 | [2 "Wednesday"]
110 | [3 "Thursday"]
111 | [4 "Friday"]
112 | [5 "Saturday"]
113 | [6 "Sunday"]
114 |
115 |
116 |
117 | ## Documentation and Tutorials
118 |
119 | You can always refer to [Simplex Wiki](https://github.com/MohammedRashad/Simplex/wiki/) for in-depth details.
120 |
121 | ## License
122 |
123 | This project is signed under GNU Public License V3.0
124 |
--------------------------------------------------------------------------------
/environment.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Mohamed Rashad
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * adouble with this program. If not, see .
16 | */
17 |
18 | #ifndef ENVIRONMENT_H
19 | #define ENVIRONMENT_H
20 |
21 | /* Lisp Environment */
22 |
23 | struct smplx_scope {
24 | smplx_scope* par;
25 | int count;
26 | char** syms;
27 | smplx_val** vals;
28 | };
29 |
30 | smplx_scope* smplx_scope_new(void) {
31 | smplx_scope* e = malloc(sizeof (smplx_scope));
32 | e->par = NULL;
33 | e->count = 0;
34 | e->syms = NULL;
35 | e->vals = NULL;
36 | return e;
37 | }
38 |
39 | void smplx_scope_del(smplx_scope* e) {
40 | for (int i = 0; i < e->count; i++) {
41 | free(e->syms[i]);
42 | smplx_val_del(e->vals[i]);
43 | }
44 | free(e->syms);
45 | free(e->vals);
46 | free(e);
47 | }
48 |
49 | smplx_scope* smplx_scope_copy(smplx_scope* e) {
50 | smplx_scope* n = malloc(sizeof (smplx_scope));
51 | n->par = e->par;
52 | n->count = e->count;
53 | n->syms = malloc(sizeof (char*) * n->count);
54 | n->vals = malloc(sizeof (smplx_val*) * n->count);
55 | for (int i = 0; i < e->count; i++) {
56 | n->syms[i] = malloc(strlen(e->syms[i]) + 1);
57 | strcpy(n->syms[i], e->syms[i]);
58 | n->vals[i] = smplx_val_copy(e->vals[i]);
59 | }
60 | return n;
61 | }
62 |
63 | smplx_val* smplx_scope_get(smplx_scope* e, smplx_val* k) {
64 |
65 | for (int i = 0; i < e->count; i++) {
66 | if (strcmp(e->syms[i], k->sym) == 0) {
67 | return smplx_val_copy(e->vals[i]);
68 | }
69 | }
70 |
71 | if (e->par) {
72 | return smplx_scope_get(e->par, k);
73 | } else {
74 | return smplx_val_err("Unbound Symbol '%s'", k->sym);
75 | }
76 | }
77 |
78 | void smplx_scope_put(smplx_scope* e, smplx_val* k, smplx_val* v) {
79 |
80 | for (int i = 0; i < e->count; i++) {
81 | if (strcmp(e->syms[i], k->sym) == 0) {
82 | smplx_val_del(e->vals[i]);
83 | e->vals[i] = smplx_val_copy(v);
84 | return;
85 | }
86 | }
87 |
88 | e->count++;
89 | e->vals = realloc(e->vals, sizeof (smplx_val*) * e->count);
90 | e->syms = realloc(e->syms, sizeof (char*) * e->count);
91 | e->vals[e->count - 1] = smplx_val_copy(v);
92 | e->syms[e->count - 1] = malloc(strlen(k->sym) + 1);
93 | strcpy(e->syms[e->count - 1], k->sym);
94 | }
95 |
96 | void smplx_scope_def(smplx_scope* e, smplx_val* k, smplx_val* v) {
97 | while (e->par) {
98 | e = e->par;
99 | }
100 | smplx_scope_put(e, k, v);
101 | }
102 |
103 |
104 | #endif /* ENVIRONMENT_H */
105 |
106 |
--------------------------------------------------------------------------------
/evaluate.h:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 |
7 | /*
8 | * File: evaluate.h
9 | * Author: root
10 | *
11 | * Created on June 15, 2017, 6:53 AM
12 | */
13 |
14 | #ifndef EVALUATE_H
15 | #define EVALUATE_H
16 |
17 | /* Evaluation */
18 |
19 | smplx_val* smplx_val_call(smplx_scope* e, smplx_val* f, smplx_val* a) {
20 |
21 | if (f->builtin) {
22 | return f->builtin(e, a);
23 | }
24 |
25 | int given = a->count;
26 | int total = f->formals->count;
27 |
28 | while (a->count) {
29 |
30 | if (f->formals->count == 0) {
31 | smplx_val_del(a);
32 | return smplx_val_err("Function passed too many arguments. "
33 | "Got %i, Expected %i.", given, total);
34 | }
35 |
36 | smplx_val* sym = smplx_val_pop(f->formals, 0);
37 |
38 | if (strcmp(sym->sym, "&") == 0) {
39 |
40 | if (f->formals->count != 1) {
41 | smplx_val_del(a);
42 | return smplx_val_err("Function format invalid. "
43 | "Symbol '&' not followed by single symbol.");
44 | }
45 |
46 | smplx_val* nsym = smplx_val_pop(f->formals, 0);
47 | smplx_scope_put(f->env, nsym, builtin_list(e, a));
48 | smplx_val_del(sym);
49 | smplx_val_del(nsym);
50 | break;
51 | }
52 |
53 | smplx_val* val = smplx_val_pop(a, 0);
54 | smplx_scope_put(f->env, sym, val);
55 | smplx_val_del(sym);
56 | smplx_val_del(val);
57 | }
58 |
59 | smplx_val_del(a);
60 |
61 | if (f->formals->count > 0 && strcmp(f->formals->cell[0]->sym, "&") == 0) {
62 |
63 | if (f->formals->count != 2) {
64 | return smplx_val_err("Function format invalid. "
65 | "Symbol '&' not followed by single symbol.");
66 | }
67 |
68 | smplx_val_del(smplx_val_pop(f->formals, 0));
69 |
70 | smplx_val* sym = smplx_val_pop(f->formals, 0);
71 | smplx_val* val = smplx_val_qexpr();
72 | smplx_scope_put(f->env, sym, val);
73 | smplx_val_del(sym);
74 | smplx_val_del(val);
75 | }
76 |
77 | if (f->formals->count == 0) {
78 | f->env->par = e;
79 | return builtin_eval(f->env, smplx_val_add(smplx_val_sexpr(), smplx_val_copy(f->body)));
80 | } else {
81 | return smplx_val_copy(f);
82 | }
83 |
84 | }
85 |
86 | smplx_val* smplx_val_eval_sexpr(smplx_scope* e, smplx_val* v) {
87 |
88 | for (int i = 0; i < v->count; i++) {
89 | v->cell[i] = smplx_val_eval(e, v->cell[i]);
90 | }
91 | for (int i = 0; i < v->count; i++) {
92 | if (v->cell[i]->type == LVAL_ERR) {
93 | return smplx_val_take(v, i);
94 | }
95 | }
96 |
97 | if (v->count == 0) {
98 | return v;
99 | }
100 | if (v->count == 1) {
101 | return smplx_val_eval(e, smplx_val_take(v, 0));
102 | }
103 |
104 | smplx_val* f = smplx_val_pop(v, 0);
105 | if (f->type != LVAL_FUN) {
106 | smplx_val* err = smplx_val_err(
107 | "S-Expression starts with incorrect type. "
108 | "Got %s, Expected %s.",
109 | ltype_name(f->type), ltype_name(LVAL_FUN));
110 | smplx_val_del(f);
111 | smplx_val_del(v);
112 | return err;
113 | }
114 |
115 | smplx_val* result = smplx_val_call(e, f, v);
116 | smplx_val_del(f);
117 | return result;
118 | }
119 |
120 | smplx_val* smplx_val_eval(smplx_scope* e, smplx_val* v) {
121 | if (v->type == LVAL_SYM) {
122 | smplx_val* x = smplx_scope_get(e, v);
123 | smplx_val_del(v);
124 | return x;
125 | }
126 | if (v->type == LVAL_SEXPR) {
127 | return smplx_val_eval_sexpr(e, v);
128 | }
129 | return v;
130 | }
131 |
132 |
133 | #endif /* EVALUATE_H */
134 |
135 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # There exist several targets which are by default empty and which can be
3 | # used for execution of your targets. These targets are usually executed
4 | # before and after some main targets. They are:
5 | #
6 | # .build-pre: called before 'build' target
7 | # .build-post: called after 'build' target
8 | # .clean-pre: called before 'clean' target
9 | # .clean-post: called after 'clean' target
10 | # .clobber-pre: called before 'clobber' target
11 | # .clobber-post: called after 'clobber' target
12 | # .all-pre: called before 'all' target
13 | # .all-post: called after 'all' target
14 | # .help-pre: called before 'help' target
15 | # .help-post: called after 'help' target
16 | #
17 | # Targets beginning with '.' are not intended to be called on their own.
18 | #
19 | # Main targets can be executed directly, and they are:
20 | #
21 | # build build a specific configuration
22 | # clean remove built files from a configuration
23 | # clobber remove all built files
24 | # all build all configurations
25 | # help print help mesage
26 | #
27 | # Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
28 | # .help-impl are implemented in nbproject/makefile-impl.mk.
29 | #
30 | # Available make variables:
31 | #
32 | # CND_BASEDIR base directory for relative paths
33 | # CND_DISTDIR default top distribution directory (build artifacts)
34 | # CND_BUILDDIR default top build directory (object files, ...)
35 | # CONF name of current configuration
36 | # CND_PLATFORM_${CONF} platform name (current configuration)
37 | # CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
38 | # CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
39 | # CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
40 | # CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
41 | # CND_PACKAGE_NAME_${CONF} name of package (current configuration)
42 | # CND_PACKAGE_PATH_${CONF} path to package (current configuration)
43 | #
44 | # NOCDDL
45 |
46 |
47 | # Environment
48 | MKDIR=mkdir
49 | CP=cp
50 | CCADMIN=CCadmin
51 |
52 |
53 | # build
54 | build: .build-post
55 |
56 | .build-pre:
57 | # Add your pre 'build' code here...
58 |
59 | .build-post: .build-impl
60 | # Add your post 'build' code here...
61 |
62 |
63 | # clean
64 | clean: .clean-post
65 |
66 | .clean-pre:
67 | # Add your pre 'clean' code here...
68 |
69 | .clean-post: .clean-impl
70 | # Add your post 'clean' code here...
71 |
72 |
73 | # clobber
74 | clobber: .clobber-post
75 |
76 | .clobber-pre:
77 | # Add your pre 'clobber' code here...
78 |
79 | .clobber-post: .clobber-impl
80 | # Add your post 'clobber' code here...
81 |
82 |
83 | # all
84 | all: .all-post
85 |
86 | .all-pre:
87 | # Add your pre 'all' code here...
88 |
89 | .all-post: .all-impl
90 | # Add your post 'all' code here...
91 |
92 |
93 | # build tests
94 | build-tests: .build-tests-post
95 |
96 | .build-tests-pre:
97 | # Add your pre 'build-tests' code here...
98 |
99 | .build-tests-post: .build-tests-impl
100 | # Add your post 'build-tests' code here...
101 |
102 |
103 | # run tests
104 | test: .test-post
105 |
106 | .test-pre: build-tests
107 | # Add your pre 'test' code here...
108 |
109 | .test-post: .test-impl
110 | # Add your post 'test' code here...
111 |
112 |
113 | # help
114 | help: .help-post
115 |
116 | .help-pre:
117 | # Add your pre 'help' code here...
118 |
119 | .help-post: .help-impl
120 | # Add your post 'help' code here...
121 |
122 |
123 |
124 | # include project implementation makefile
125 | include nbproject/Makefile-impl.mk
126 |
127 | # include project make variables
128 | include nbproject/Makefile-variables.mk
129 |
--------------------------------------------------------------------------------
/main.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Mohamed Rashad
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * adouble with this program. If not, see .
16 | */
17 |
18 | #include "Simplex.h"
19 |
20 | int zstring_search_chr(const char *token,char s){
21 | if (!token || s=='\0')
22 | return 0;
23 |
24 | for (;*token; token++)
25 | if (*token == s)
26 | return 1;
27 |
28 | return 0;
29 | }
30 |
31 |
32 | char *zstring_remove_chr(char *str,const char *bad) {
33 | char *src = str , *dst = str;
34 | while(*src)
35 | if(zstring_search_chr(bad,*src))
36 | src++;
37 | else
38 | *dst++ = *src++; /* assign first, then incement */
39 |
40 | *dst='\0';
41 | return str;
42 | }
43 |
44 |
45 |
46 | int main(int argc, char** argv) {
47 |
48 | char input[4096];
49 |
50 | Number = mpc_new("number");
51 | Symbol = mpc_new("symbol");
52 | String = mpc_new("string");
53 | Comment = mpc_new("comment");
54 | Sexpr = mpc_new("sexpr");
55 | Qexpr = mpc_new("qexpr");
56 | Expr = mpc_new("expr");
57 | Lispy = mpc_new("simplex");
58 |
59 | mpca_lang(MPCA_LANG_DEFAULT,
60 | " \
61 | number : /-?[0-9]+(\\.[0-9]+)?/ ; \
62 | symbol : /[a-zA-Z0-9_+\\-*\\/\\\\@=<>!&]+/ ; \
63 | string : /\"(\\\\.|[^\"])*\"/ ; \
64 | comment : /#[^\\r\\n]*/ ; \
65 | sexpr : '(' * ')' | ; \
66 | qexpr : '[' * ']' ; \
67 | expr : | | \
68 | | | | ; \
69 | simplex : /^/ * /$/ ; \
70 | ",
71 | Number, Symbol, String, Comment, Sexpr, Qexpr, Expr, Lispy);
72 |
73 | smplx_scope* e = smplx_scope_new();
74 | smplx_scope_add_builtins(e);
75 |
76 | /* Interactive Mode */
77 | if (argc == 1) {
78 |
79 | puts("Simplex BETA (V0.1) -- Interactive Mode");
80 | puts("Press Ctrl+c to Exit\n");
81 |
82 | while (1) {
83 |
84 | printf("Simplex > ");
85 |
86 | fgets(input, 4096, stdin);
87 |
88 | mpc_result_t r;
89 | if (mpc_parse("", zstring_remove_chr(input,";"), Lispy, &r)) {
90 |
91 | smplx_val* expr = smplx_val_read(r.output);
92 |
93 | smplx_val* x = smplx_val_eval(e, expr);
94 | smplx_val_println(x);
95 | smplx_val_del(x);
96 |
97 | mpc_ast_delete(r.output);
98 | } else {
99 | mpc_err_print(r.error);
100 | mpc_err_delete(r.error);
101 | }
102 |
103 |
104 | }
105 | }
106 |
107 | /* Batch Mode */
108 | if (argc >= 2) {
109 |
110 | /* loop over each supplied filename (starting from 1) */
111 | for (int i = 1; i < argc; i++) {
112 |
113 | /* Argument list with a single argument, the filename */
114 | smplx_val* args = smplx_val_add(smplx_val_sexpr(), smplx_val_str(argv[i]));
115 |
116 | /* Pass to builtin load and get the result */
117 | smplx_val* x = builtin_load(e, args);
118 |
119 | /* If the result is an error be sure to print it */
120 | if (x->type == LVAL_ERR) {
121 | smplx_val_println(x);
122 | }
123 | smplx_val_del(x);
124 | }
125 | }
126 |
127 | /* Cleaning up resources */
128 | smplx_scope_del(e);
129 |
130 | mpc_cleanup(8, Number, Symbol, String, Comment, Sexpr, Qexpr, Expr, Lispy);
131 |
132 | return 0;
133 | }
--------------------------------------------------------------------------------
/nbproject/configurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 | Simplex.h
8 | built_in.h
9 | definitions.h
10 | environment.h
11 | evaluate.h
12 | lexer.h
13 | mpc.h
14 |
15 |
18 |
19 |
22 | main.c
23 | mpc.c
24 |
25 |
29 |
30 |
34 | Makefile
35 |
36 | code.sx
37 | std.sx
38 |
39 | Makefile
40 |
41 |
42 |
43 | default
44 | true
45 | false
46 |
47 |
48 |
49 | -
50 |
51 | -
52 |
53 | -
54 |
55 | -
56 |
57 | -
58 |
59 | -
60 |
61 | -
62 |
63 | -
64 |
65 | -
66 |
67 | -
68 |
69 | -
70 |
71 |
72 |
73 |
74 | default
75 | true
76 | false
77 |
78 |
79 |
80 | 5
81 |
82 |
83 | 5
84 |
85 |
86 | 5
87 |
88 |
89 | 5
90 |
91 |
92 | -
93 |
94 | -
95 |
96 | -
97 |
98 | -
99 |
100 | -
101 |
102 | -
103 |
104 | -
105 |
106 | -
107 |
108 | -
109 |
110 | -
111 |
112 | -
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/nbproject/Makefile-impl.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Generated Makefile - do not edit!
3 | #
4 | # Edit the Makefile in the project folder instead (../Makefile). Each target
5 | # has a pre- and a post- target defined where you can add customization code.
6 | #
7 | # This makefile implements macros and targets common to all configurations.
8 | #
9 | # NOCDDL
10 |
11 |
12 | # Building and Cleaning subprojects are done by default, but can be controlled with the SUB
13 | # macro. If SUB=no, subprojects will not be built or cleaned. The following macro
14 | # statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf
15 | # and .clean-reqprojects-conf unless SUB has the value 'no'
16 | SUB_no=NO
17 | SUBPROJECTS=${SUB_${SUB}}
18 | BUILD_SUBPROJECTS_=.build-subprojects
19 | BUILD_SUBPROJECTS_NO=
20 | BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}}
21 | CLEAN_SUBPROJECTS_=.clean-subprojects
22 | CLEAN_SUBPROJECTS_NO=
23 | CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
24 |
25 |
26 | # Project Name
27 | PROJECTNAME=Simplex
28 |
29 | # Active Configuration
30 | DEFAULTCONF=Debug
31 | CONF=${DEFAULTCONF}
32 |
33 | # All Configurations
34 | ALLCONFS=Debug Release
35 |
36 |
37 | # build
38 | .build-impl: .build-pre .validate-impl .depcheck-impl
39 | @#echo "=> Running $@... Configuration=$(CONF)"
40 | "${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf
41 |
42 |
43 | # clean
44 | .clean-impl: .clean-pre .validate-impl .depcheck-impl
45 | @#echo "=> Running $@... Configuration=$(CONF)"
46 | "${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf
47 |
48 |
49 | # clobber
50 | .clobber-impl: .clobber-pre .depcheck-impl
51 | @#echo "=> Running $@..."
52 | for CONF in ${ALLCONFS}; \
53 | do \
54 | "${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf; \
55 | done
56 |
57 | # all
58 | .all-impl: .all-pre .depcheck-impl
59 | @#echo "=> Running $@..."
60 | for CONF in ${ALLCONFS}; \
61 | do \
62 | "${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf; \
63 | done
64 |
65 | # build tests
66 | .build-tests-impl: .build-impl .build-tests-pre
67 | @#echo "=> Running $@... Configuration=$(CONF)"
68 | "${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-tests-conf
69 |
70 | # run tests
71 | .test-impl: .build-tests-impl .test-pre
72 | @#echo "=> Running $@... Configuration=$(CONF)"
73 | "${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .test-conf
74 |
75 | # dependency checking support
76 | .depcheck-impl:
77 | @echo "# This code depends on make tool being used" >.dep.inc
78 | @if [ -n "${MAKE_VERSION}" ]; then \
79 | echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES} \$${TESTOBJECTFILES}))" >>.dep.inc; \
80 | echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
81 | echo "include \$${DEPFILES}" >>.dep.inc; \
82 | echo "endif" >>.dep.inc; \
83 | else \
84 | echo ".KEEP_STATE:" >>.dep.inc; \
85 | echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
86 | fi
87 |
88 | # configuration validation
89 | .validate-impl:
90 | @if [ ! -f nbproject/Makefile-${CONF}.mk ]; \
91 | then \
92 | echo ""; \
93 | echo "Error: can not find the makefile for configuration '${CONF}' in project ${PROJECTNAME}"; \
94 | echo "See 'make help' for details."; \
95 | echo "Current directory: " `pwd`; \
96 | echo ""; \
97 | fi
98 | @if [ ! -f nbproject/Makefile-${CONF}.mk ]; \
99 | then \
100 | exit 1; \
101 | fi
102 |
103 |
104 | # help
105 | .help-impl: .help-pre
106 | @echo "This makefile supports the following configurations:"
107 | @echo " ${ALLCONFS}"
108 | @echo ""
109 | @echo "and the following targets:"
110 | @echo " build (default target)"
111 | @echo " clean"
112 | @echo " clobber"
113 | @echo " all"
114 | @echo " help"
115 | @echo ""
116 | @echo "Makefile Usage:"
117 | @echo " make [CONF=] [SUB=no] build"
118 | @echo " make [CONF=] [SUB=no] clean"
119 | @echo " make [SUB=no] clobber"
120 | @echo " make [SUB=no] all"
121 | @echo " make help"
122 | @echo ""
123 | @echo "Target 'build' will build a specific configuration and, unless 'SUB=no',"
124 | @echo " also build subprojects."
125 | @echo "Target 'clean' will clean a specific configuration and, unless 'SUB=no',"
126 | @echo " also clean subprojects."
127 | @echo "Target 'clobber' will remove all built files from all configurations and,"
128 | @echo " unless 'SUB=no', also from subprojects."
129 | @echo "Target 'all' will will build all configurations and, unless 'SUB=no',"
130 | @echo " also build subprojects."
131 | @echo "Target 'help' prints this message."
132 | @echo ""
133 |
134 |
--------------------------------------------------------------------------------
/Standard Library/std.sx:
--------------------------------------------------------------------------------
1 | #
2 | # Simplex Standard Library
3 | #
4 |
5 | # Atoms
6 | (define [null] [])
7 | (define [true] 1)
8 | (define [false] 0)
9 |
10 | # Functional Functions
11 |
12 | # Function Definitions
13 | (define [fun] (@ [f b] [
14 | define (head f) (@ (tail f) b)
15 | ]))
16 |
17 | # Open new scope
18 | (fun [open b] [
19 | ((@ [_] b) ())
20 | ])
21 |
22 | # Unpack List to Function
23 | (fun [unpack f l] [
24 | eval (join (list f) l)
25 | ])
26 |
27 | # Unapply List to Function
28 | (fun [pack f & xs]
29 | [f xs])
30 |
31 | # Curried and Uncurried calling
32 | (define [curry] unpack)
33 | (define [uncurry] pack)
34 |
35 | # Perform Several things in Sequence
36 | (fun [do & l] [
37 | if (== l null)
38 | [null]
39 | [last l]
40 | ])
41 |
42 | # Logical Functions
43 |
44 | # Logical Functions
45 | (fun [not x] [- 1 x])
46 | (fun [or x y] [+ x y])
47 | (fun [and x y] [* x y])
48 |
49 |
50 | # Numeric Functions
51 |
52 | # Minimum of Arguments
53 | (fun [min & xs] [
54 | if (== (tail xs) null) [fst xs]
55 | [do
56 | (= [rest] (unpack min (tail xs)))
57 | (= [item] (fst xs))
58 | (if (< item rest) [item] [rest])
59 | ]
60 | ])
61 |
62 | # Maximum of Arguments
63 | (fun [max & xs] [
64 | if (== (tail xs) null) [fst xs]
65 | [do
66 | (= [rest] (unpack max (tail xs)))
67 | (= [item] (fst xs))
68 | (if (> item rest) [item] [rest])
69 | ]
70 | ])
71 |
72 | # Conditional Functions
73 |
74 | (fun [select & cs] [
75 | if (== cs null)
76 | [error "No Selection Found"]
77 | [if (fst (fst cs)) [snd (fst cs)] [unpack select (tail cs)]]
78 | ])
79 |
80 | (fun [case x & cs] [
81 | if (== cs null)
82 | [error "No Case Found"]
83 | [if (== x (fst (fst cs))) [snd (fst cs)] [
84 | unpack case (join (list x) (tail cs))]]
85 | ])
86 |
87 | (define [otherwise] true)
88 |
89 |
90 | # Misc Functions
91 |
92 | (fun [flip f a b] [f b a])
93 | (fun [ghost & xs] [eval xs])
94 | (fun [comp f g x] [f (g x)])
95 |
96 | # List Functions
97 |
98 | # First, Second, or Third Item in List
99 | (fun [fst l] [ eval (head l) ])
100 | (fun [snd l] [ eval (head (tail l)) ])
101 | (fun [trd l] [ eval (head (tail (tail l))) ])
102 |
103 | # List Length
104 | (fun [len l] [
105 | if (== l null)
106 | [0]
107 | [+ 1 (len (tail l))]
108 | ])
109 |
110 | # Nth item in List
111 | (fun [nth n l] [
112 | if (== n 0)
113 | [fst l]
114 | [nth (- n 1) (tail l)]
115 | ])
116 |
117 | # Last item in List
118 | (fun [last l] [nth (- (len l) 1) l])
119 |
120 | # Apply Function to List
121 | (fun [map f l] [
122 | if (== l null)
123 | [null]
124 | [join (list (f (fst l))) (map f (tail l))]
125 | ])
126 |
127 | # Apply Filter to List
128 | (fun [filter f l] [
129 | if (== l null)
130 | [null]
131 | [join (if (f (fst l)) [head l] [null]) (filter f (tail l))]
132 | ])
133 |
134 | # Return all of list but last element
135 | (fun [init l] [
136 | if (== (tail l) null)
137 | [null]
138 | [join (head l) (init (tail l))]
139 | ])
140 |
141 | # Reverse List
142 | (fun [reverse l] [
143 | if (== l null)
144 | [null]
145 | [join (reverse (tail l)) (head l)]
146 | ])
147 |
148 | # Fold Left
149 | (fun [foldl f z l] [
150 | if (== l null)
151 | [z]
152 | [foldl f (f z (fst l)) (tail l)]
153 | ])
154 |
155 | # Fold Right
156 | (fun [foldr f z l] [
157 | if (== l null)
158 | [z]
159 | [f (fst l) (foldr f z (tail l))]
160 | ])
161 |
162 | (fun [sum l] [foldl + 0 l])
163 | (fun [product l] [foldl * 1 l])
164 |
165 | # Take N items
166 | (fun [take n l] [
167 | if (== n 0)
168 | [null]
169 | [join (head l) (take (- n 1) (tail l))]
170 | ])
171 |
172 | # Drop N items
173 | (fun [drop n l] [
174 | if (== n 0)
175 | [l]
176 | [drop (- n 1) (tail l)]
177 | ])
178 |
179 | # Split at N
180 | (fun [split n l] [list (take n l) (drop n l)])
181 |
182 | # Take While
183 | (fun [take-while f l] [
184 | if (not (unpack f (head l)))
185 | [null]
186 | [join (head l) (take-while f (tail l))]
187 | ])
188 |
189 | # Drop While
190 | (fun [drop-while f l] [
191 | if (not (unpack f (head l)))
192 | [l]
193 | [drop-while f (tail l)]
194 | ])
195 |
196 | # Element of List
197 | (fun [elem x l] [
198 | if (== l null)
199 | [false]
200 | [if (== x (fst l)) [true] [elem x (tail l)]]
201 | ])
202 |
203 | # Find element in list of pairs
204 | (fun [lookup x l] [
205 | if (== l null)
206 | [error "No Element Found"]
207 | [do
208 | (= [key] (fst (fst l)))
209 | (= [val] (snd (fst l)))
210 | (if (== key x) [val] [lookup x (tail l)])
211 | ]
212 | ])
213 |
214 | # Zip two lists together into a list of pairs
215 | (fun [zip x y] [
216 | if (or (== x null) (== y null))
217 | [null]
218 | [join (list (join (head x) (head y))) (zip (tail x) (tail y))]
219 | ])
220 |
221 | # Unzip a list of pairs into two lists
222 | (fun [unzip l] [
223 | if (== l null)
224 | [[null null]]
225 | [do
226 | (= [x] (fst l))
227 | (= [xs] (unzip (tail l)))
228 | (list (join (head x) (fst xs)) (join (tail x) (snd xs)))
229 | ]
230 | ])
231 |
232 | # Other Fun
233 |
234 | # Fibonacci
235 | (fun [fib n] [
236 | select
237 | [ (== n 0) 0 ]
238 | [ (== n 1) 1 ]
239 | [ otherwise (+ (fib (- n 1)) (fib (- n 2))) ]
240 | ])
241 |
--------------------------------------------------------------------------------
/definitions.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Mohamed Rashad
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * adouble with this program. If not, see .
16 | */
17 | #include "mpc.h"
18 |
19 | #ifndef DEFINITIONS_H
20 | #define DEFINITIONS_H
21 |
22 | mpc_parser_t* Number;
23 | mpc_parser_t* Symbol;
24 | mpc_parser_t* String;
25 | mpc_parser_t* Comment;
26 | mpc_parser_t* Sexpr;
27 | mpc_parser_t* Qexpr;
28 | mpc_parser_t* Expr;
29 | mpc_parser_t* Lispy;
30 |
31 | /* Forward Declarations */
32 |
33 | struct smplx_val;
34 | struct smplx_scope;
35 | typedef struct smplx_val smplx_val;
36 | typedef struct smplx_scope smplx_scope;
37 |
38 | /* Lisp Value */
39 |
40 | enum {
41 | LVAL_ERR, LVAL_NUM, LVAL_SYM, LVAL_STR,
42 | LVAL_FUN, LVAL_SEXPR, LVAL_QEXPR
43 | };
44 |
45 | typedef smplx_val* (*lbuiltin) (smplx_scope*, smplx_val*);
46 |
47 | struct smplx_val {
48 | int type;
49 |
50 | /* Basic */
51 | double num;
52 | char* err;
53 | char* sym;
54 | char* str;
55 |
56 | /* Function */
57 | lbuiltin builtin;
58 | smplx_scope* env;
59 | smplx_val* formals;
60 | smplx_val* body;
61 |
62 | /* Expression */
63 | int count;
64 | smplx_val** cell;
65 | };
66 |
67 | smplx_val* smplx_val_num(double x) {
68 | smplx_val* v = malloc(sizeof (smplx_val));
69 | v->type = LVAL_NUM;
70 | v->num = x;
71 | return v;
72 | }
73 |
74 | smplx_val* smplx_val_err(char* fmt, ...) {
75 | smplx_val* v = malloc(sizeof (smplx_val));
76 | v->type = LVAL_ERR;
77 | va_list va;
78 | va_start(va, fmt);
79 | v->err = malloc(512);
80 | vsnprintf(v->err, 511, fmt, va);
81 | v->err = realloc(v->err, strlen(v->err) + 1);
82 | va_end(va);
83 | return v;
84 | }
85 |
86 | smplx_val* smplx_val_sym(char* s) {
87 | smplx_val* v = malloc(sizeof (smplx_val));
88 | v->type = LVAL_SYM;
89 | v->sym = malloc(strlen(s) + 1);
90 | strcpy(v->sym, s);
91 | return v;
92 | }
93 |
94 | smplx_val* smplx_val_str(char* s) {
95 | smplx_val* v = malloc(sizeof (smplx_val));
96 | v->type = LVAL_STR;
97 | v->str = malloc(strlen(s) + 1);
98 | strcpy(v->str, s);
99 | return v;
100 | }
101 |
102 | smplx_val* smplx_val_builtin(lbuiltin func) {
103 | smplx_val* v = malloc(sizeof (smplx_val));
104 | v->type = LVAL_FUN;
105 | v->builtin = func;
106 | return v;
107 | }
108 |
109 | smplx_scope* smplx_scope_new(void);
110 |
111 | smplx_val* smplx_val_lambda(smplx_val* formals, smplx_val* body) {
112 | smplx_val* v = malloc(sizeof (smplx_val));
113 | v->type = LVAL_FUN;
114 | v->builtin = NULL;
115 | v->env = smplx_scope_new();
116 | v->formals = formals;
117 | v->body = body;
118 | return v;
119 | }
120 |
121 | smplx_val* smplx_val_sexpr(void) {
122 | smplx_val* v = malloc(sizeof (smplx_val));
123 | v->type = LVAL_SEXPR;
124 | v->count = 0;
125 | v->cell = NULL;
126 | return v;
127 | }
128 |
129 | smplx_val* smplx_val_qexpr(void) {
130 | smplx_val* v = malloc(sizeof (smplx_val));
131 | v->type = LVAL_QEXPR;
132 | v->count = 0;
133 | v->cell = NULL;
134 | return v;
135 | }
136 |
137 | void smplx_scope_del(smplx_scope* e);
138 |
139 | void smplx_val_del(smplx_val* v) {
140 |
141 | switch (v->type) {
142 | case LVAL_NUM: break;
143 | case LVAL_FUN:
144 | if (!v->builtin) {
145 | smplx_scope_del(v->env);
146 | smplx_val_del(v->formals);
147 | smplx_val_del(v->body);
148 | }
149 | break;
150 | case LVAL_ERR: free(v->err);
151 | break;
152 | case LVAL_SYM: free(v->sym);
153 | break;
154 | case LVAL_STR: free(v->str);
155 | break;
156 | case LVAL_QEXPR:
157 | case LVAL_SEXPR:
158 | for (int i = 0; i < v->count; i++) {
159 | smplx_val_del(v->cell[i]);
160 | }
161 | free(v->cell);
162 | break;
163 | }
164 |
165 | free(v);
166 | }
167 |
168 | smplx_scope* smplx_scope_copy(smplx_scope* e);
169 |
170 | smplx_val* smplx_val_copy(smplx_val* v) {
171 | smplx_val* x = malloc(sizeof (smplx_val));
172 | x->type = v->type;
173 | switch (v->type) {
174 | case LVAL_FUN:
175 | if (v->builtin) {
176 | x->builtin = v->builtin;
177 | } else {
178 | x->builtin = NULL;
179 | x->env = smplx_scope_copy(v->env);
180 | x->formals = smplx_val_copy(v->formals);
181 | x->body = smplx_val_copy(v->body);
182 | }
183 | break;
184 | case LVAL_NUM: x->num = v->num;
185 | break;
186 | case LVAL_ERR: x->err = malloc(strlen(v->err) + 1);
187 | strcpy(x->err, v->err);
188 | break;
189 | case LVAL_SYM: x->sym = malloc(strlen(v->sym) + 1);
190 | strcpy(x->sym, v->sym);
191 | break;
192 | case LVAL_STR: x->str = malloc(strlen(v->str) + 1);
193 | strcpy(x->str, v->str);
194 | break;
195 | case LVAL_SEXPR:
196 | case LVAL_QEXPR:
197 | x->count = v->count;
198 | x->cell = malloc(sizeof (smplx_val*) * x->count);
199 | for (int i = 0; i < x->count; i++) {
200 | x->cell[i] = smplx_val_copy(v->cell[i]);
201 | }
202 | break;
203 | }
204 | return x;
205 | }
206 |
207 | smplx_val* smplx_val_add(smplx_val* v, smplx_val* x) {
208 | v->count++;
209 | v->cell = realloc(v->cell, sizeof (smplx_val*) * v->count);
210 | v->cell[v->count - 1] = x;
211 | return v;
212 | }
213 |
214 | smplx_val* smplx_val_join(smplx_val* x, smplx_val* y) {
215 | for (int i = 0; i < y->count; i++) {
216 | x = smplx_val_add(x, y->cell[i]);
217 | }
218 | free(y->cell);
219 | free(y);
220 | return x;
221 | }
222 |
223 | smplx_val* smplx_val_pop(smplx_val* v, int i) {
224 | smplx_val* x = v->cell[i];
225 | memmove(&v->cell[i],
226 | &v->cell[i + 1], sizeof (smplx_val*) * (v->count - i - 1));
227 | v->count--;
228 | v->cell = realloc(v->cell, sizeof (smplx_val*) * v->count);
229 | return x;
230 | }
231 |
232 | smplx_val* smplx_val_take(smplx_val* v, int i) {
233 | smplx_val* x = smplx_val_pop(v, i);
234 | smplx_val_del(v);
235 | return x;
236 | }
237 |
238 | void smplx_val_print(smplx_val* v);
239 |
240 | void smplx_val_print_expr(smplx_val* v, char open, char close) {
241 | putchar(open);
242 | for (int i = 0; i < v->count; i++) {
243 | smplx_val_print(v->cell[i]);
244 | if (i != (v->count - 1)) {
245 | putchar(' ');
246 | }
247 | }
248 | putchar(close);
249 | }
250 |
251 | void smplx_val_print_str(smplx_val* v) {
252 | /* Make a Copy of the string */
253 | char* escaped = malloc(strlen(v->str) + 1);
254 | strcpy(escaped, v->str);
255 | /* Pass it through the escape function */
256 | escaped = mpcf_escape(escaped);
257 | /* Print it between " characters */
258 | printf("\"%s\"", escaped);
259 | /* free the copied string */
260 | free(escaped);
261 | }
262 |
263 | void smplx_val_print(smplx_val* v) {
264 | switch (v->type) {
265 | case LVAL_FUN:
266 | if (v->builtin) {
267 | printf("");
268 | } else {
269 | printf("(@ ");
270 | smplx_val_print(v->formals);
271 | putchar(' ');
272 | smplx_val_print(v->body);
273 | putchar(')');
274 | }
275 | break;
276 | case LVAL_NUM: printf("%.3f", v->num);
277 | break;
278 | case LVAL_ERR: printf("Error: %s", v->err);
279 | break;
280 | case LVAL_SYM: printf("%s", v->sym);
281 | break;
282 | case LVAL_STR: smplx_val_print_str(v);
283 | break;
284 | case LVAL_SEXPR: smplx_val_print_expr(v, '(', ')');
285 | break;
286 | case LVAL_QEXPR: smplx_val_print_expr(v, '[', ']');
287 | break;
288 | }
289 | }
290 |
291 | void smplx_val_println(smplx_val* v) {
292 | smplx_val_print(v);
293 | putchar('\n');
294 | }
295 |
296 | int smplx_val_eq(smplx_val* x, smplx_val* y) {
297 |
298 | if (x->type != y->type) {
299 | return 0;
300 | }
301 |
302 | switch (x->type) {
303 | case LVAL_NUM: return (x->num == y->num);
304 | case LVAL_ERR: return (strcmp(x->err, y->err) == 0);
305 | case LVAL_SYM: return (strcmp(x->sym, y->sym) == 0);
306 | case LVAL_STR: return (strcmp(x->str, y->str) == 0);
307 | case LVAL_FUN:
308 | if (x->builtin || y->builtin) {
309 | return x->builtin == y->builtin;
310 | } else {
311 | return smplx_val_eq(x->formals, y->formals) && smplx_val_eq(x->body, y->body);
312 | }
313 | case LVAL_QEXPR:
314 | case LVAL_SEXPR:
315 | if (x->count != y->count) {
316 | return 0;
317 | }
318 | for (int i = 0; i < x->count; i++) {
319 | if (!smplx_val_eq(x->cell[i], y->cell[i])) {
320 | return 0;
321 | }
322 | }
323 | return 1;
324 | break;
325 | }
326 | return 0;
327 | }
328 |
329 | char* ltype_name(int t) {
330 | switch (t) {
331 | case LVAL_FUN: return "Function";
332 | case LVAL_NUM: return "Number";
333 | case LVAL_ERR: return "Error";
334 | case LVAL_SYM: return "Symbol";
335 | case LVAL_STR: return "String";
336 | case LVAL_SEXPR: return "S-Expression";
337 | case LVAL_QEXPR: return "Q-Expression";
338 | default: return "Unknown";
339 | }
340 | }
341 |
342 |
343 | #endif /* DEFINITIONS_H */
344 |
345 |
--------------------------------------------------------------------------------
/mpc.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** mpc - Micro Parser Combinator library for C
3 | **
4 | ** https://github.com/orangeduck/mpc
5 | **
6 | ** Daniel Holden - contact@daniel-holden.com
7 | ** Licensed under BSD3
8 | */
9 |
10 | #ifndef mpc_h
11 | #define mpc_h
12 |
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | /*
22 | ** State Type
23 | */
24 |
25 | typedef struct {
26 | long pos;
27 | long row;
28 | long col;
29 | } mpc_state_t;
30 |
31 | /*
32 | ** Error Type
33 | */
34 |
35 | typedef struct {
36 | mpc_state_t state;
37 | int expected_num;
38 | char *filename;
39 | char *failure;
40 | char **expected;
41 | char recieved;
42 | } mpc_err_t;
43 |
44 | void mpc_err_delete(mpc_err_t *e);
45 | char *mpc_err_string(mpc_err_t *e);
46 | void mpc_err_print(mpc_err_t *e);
47 | void mpc_err_print_to(mpc_err_t *e, FILE *f);
48 |
49 | /*
50 | ** Parsing
51 | */
52 |
53 | typedef void mpc_val_t;
54 |
55 | typedef union {
56 | mpc_err_t *error;
57 | mpc_val_t *output;
58 | } mpc_result_t;
59 |
60 | struct mpc_parser_t;
61 | typedef struct mpc_parser_t mpc_parser_t;
62 |
63 | int mpc_parse(const char *filename, const char *string, mpc_parser_t *p, mpc_result_t *r);
64 | int mpc_parse_file(const char *filename, FILE *file, mpc_parser_t *p, mpc_result_t *r);
65 | int mpc_parse_pipe(const char *filename, FILE *pipe, mpc_parser_t *p, mpc_result_t *r);
66 | int mpc_parse_contents(const char *filename, mpc_parser_t *p, mpc_result_t *r);
67 |
68 | /*
69 | ** Function Types
70 | */
71 |
72 | typedef void(*mpc_dtor_t)(mpc_val_t*);
73 | typedef mpc_val_t*(*mpc_ctor_t)(void);
74 |
75 | typedef mpc_val_t*(*mpc_apply_t)(mpc_val_t*);
76 | typedef mpc_val_t*(*mpc_apply_to_t)(mpc_val_t*,void*);
77 | typedef mpc_val_t*(*mpc_fold_t)(int,mpc_val_t**);
78 |
79 | /*
80 | ** Building a Parser
81 | */
82 |
83 | mpc_parser_t *mpc_new(const char *name);
84 | mpc_parser_t *mpc_define(mpc_parser_t *p, mpc_parser_t *a);
85 | mpc_parser_t *mpc_undefine(mpc_parser_t *p);
86 |
87 | void mpc_delete(mpc_parser_t *p);
88 | void mpc_cleanup(int n, ...);
89 |
90 | /*
91 | ** Basic Parsers
92 | */
93 |
94 | mpc_parser_t *mpc_any(void);
95 | mpc_parser_t *mpc_char(char c);
96 | mpc_parser_t *mpc_range(char s, char e);
97 | mpc_parser_t *mpc_oneof(const char *s);
98 | mpc_parser_t *mpc_noneof(const char *s);
99 | mpc_parser_t *mpc_satisfy(int(*f)(char));
100 | mpc_parser_t *mpc_string(const char *s);
101 |
102 | /*
103 | ** Other Parsers
104 | */
105 |
106 | mpc_parser_t *mpc_pass(void);
107 | mpc_parser_t *mpc_fail(const char *m);
108 | mpc_parser_t *mpc_failf(const char *fmt, ...);
109 | mpc_parser_t *mpc_lift(mpc_ctor_t f);
110 | mpc_parser_t *mpc_lift_val(mpc_val_t *x);
111 | mpc_parser_t *mpc_anchor(int(*f)(char,char));
112 | mpc_parser_t *mpc_state(void);
113 |
114 | /*
115 | ** Combinator Parsers
116 | */
117 |
118 | mpc_parser_t *mpc_expect(mpc_parser_t *a, const char *e);
119 | mpc_parser_t *mpc_expectf(mpc_parser_t *a, const char *fmt, ...);
120 | mpc_parser_t *mpc_apply(mpc_parser_t *a, mpc_apply_t f);
121 | mpc_parser_t *mpc_apply_to(mpc_parser_t *a, mpc_apply_to_t f, void *x);
122 |
123 | mpc_parser_t *mpc_not(mpc_parser_t *a, mpc_dtor_t da);
124 | mpc_parser_t *mpc_not_lift(mpc_parser_t *a, mpc_dtor_t da, mpc_ctor_t lf);
125 | mpc_parser_t *mpc_maybe(mpc_parser_t *a);
126 | mpc_parser_t *mpc_maybe_lift(mpc_parser_t *a, mpc_ctor_t lf);
127 |
128 | mpc_parser_t *mpc_many(mpc_fold_t f, mpc_parser_t *a);
129 | mpc_parser_t *mpc_many1(mpc_fold_t f, mpc_parser_t *a);
130 | mpc_parser_t *mpc_count(int n, mpc_fold_t f, mpc_parser_t *a, mpc_dtor_t da);
131 |
132 | mpc_parser_t *mpc_or(int n, ...);
133 | mpc_parser_t *mpc_and(int n, mpc_fold_t f, ...);
134 |
135 | mpc_parser_t *mpc_predictive(mpc_parser_t *a);
136 |
137 | /*
138 | ** Common Parsers
139 | */
140 |
141 | mpc_parser_t *mpc_eoi(void);
142 | mpc_parser_t *mpc_soi(void);
143 |
144 | mpc_parser_t *mpc_boundary(void);
145 |
146 | mpc_parser_t *mpc_whitespace(void);
147 | mpc_parser_t *mpc_whitespaces(void);
148 | mpc_parser_t *mpc_blank(void);
149 |
150 | mpc_parser_t *mpc_newline(void);
151 | mpc_parser_t *mpc_tab(void);
152 | mpc_parser_t *mpc_escape(void);
153 |
154 | mpc_parser_t *mpc_digit(void);
155 | mpc_parser_t *mpc_hexdigit(void);
156 | mpc_parser_t *mpc_octdigit(void);
157 | mpc_parser_t *mpc_digits(void);
158 | mpc_parser_t *mpc_hexdigits(void);
159 | mpc_parser_t *mpc_octdigits(void);
160 |
161 | mpc_parser_t *mpc_lower(void);
162 | mpc_parser_t *mpc_upper(void);
163 | mpc_parser_t *mpc_alpha(void);
164 | mpc_parser_t *mpc_underscore(void);
165 | mpc_parser_t *mpc_alphanum(void);
166 |
167 | mpc_parser_t *mpc_int(void);
168 | mpc_parser_t *mpc_hex(void);
169 | mpc_parser_t *mpc_oct(void);
170 | mpc_parser_t *mpc_number(void);
171 |
172 | mpc_parser_t *mpc_real(void);
173 | mpc_parser_t *mpc_float(void);
174 |
175 | mpc_parser_t *mpc_char_lit(void);
176 | mpc_parser_t *mpc_string_lit(void);
177 | mpc_parser_t *mpc_regex_lit(void);
178 |
179 | mpc_parser_t *mpc_ident(void);
180 |
181 | /*
182 | ** Useful Parsers
183 | */
184 |
185 | mpc_parser_t *mpc_startwith(mpc_parser_t *a);
186 | mpc_parser_t *mpc_endwith(mpc_parser_t *a, mpc_dtor_t da);
187 | mpc_parser_t *mpc_whole(mpc_parser_t *a, mpc_dtor_t da);
188 |
189 | mpc_parser_t *mpc_stripl(mpc_parser_t *a);
190 | mpc_parser_t *mpc_stripr(mpc_parser_t *a);
191 | mpc_parser_t *mpc_strip(mpc_parser_t *a);
192 | mpc_parser_t *mpc_tok(mpc_parser_t *a);
193 | mpc_parser_t *mpc_sym(const char *s);
194 | mpc_parser_t *mpc_total(mpc_parser_t *a, mpc_dtor_t da);
195 |
196 | mpc_parser_t *mpc_between(mpc_parser_t *a, mpc_dtor_t ad, const char *o, const char *c);
197 | mpc_parser_t *mpc_parens(mpc_parser_t *a, mpc_dtor_t ad);
198 | mpc_parser_t *mpc_braces(mpc_parser_t *a, mpc_dtor_t ad);
199 | mpc_parser_t *mpc_brackets(mpc_parser_t *a, mpc_dtor_t ad);
200 | mpc_parser_t *mpc_squares(mpc_parser_t *a, mpc_dtor_t ad);
201 |
202 | mpc_parser_t *mpc_tok_between(mpc_parser_t *a, mpc_dtor_t ad, const char *o, const char *c);
203 | mpc_parser_t *mpc_tok_parens(mpc_parser_t *a, mpc_dtor_t ad);
204 | mpc_parser_t *mpc_tok_braces(mpc_parser_t *a, mpc_dtor_t ad);
205 | mpc_parser_t *mpc_tok_brackets(mpc_parser_t *a, mpc_dtor_t ad);
206 | mpc_parser_t *mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad);
207 |
208 | /*
209 | ** Common Function Parameters
210 | */
211 |
212 | void mpcf_dtor_null(mpc_val_t *x);
213 |
214 | mpc_val_t *mpcf_ctor_null(void);
215 | mpc_val_t *mpcf_ctor_str(void);
216 |
217 | mpc_val_t *mpcf_free(mpc_val_t *x);
218 | mpc_val_t *mpcf_int(mpc_val_t *x);
219 | mpc_val_t *mpcf_hex(mpc_val_t *x);
220 | mpc_val_t *mpcf_oct(mpc_val_t *x);
221 | mpc_val_t *mpcf_float(mpc_val_t *x);
222 | mpc_val_t *mpcf_strtriml(mpc_val_t *x);
223 | mpc_val_t *mpcf_strtrimr(mpc_val_t *x);
224 | mpc_val_t *mpcf_strtrim(mpc_val_t *x);
225 |
226 | mpc_val_t *mpcf_escape(mpc_val_t *x);
227 | mpc_val_t *mpcf_escape_regex(mpc_val_t *x);
228 | mpc_val_t *mpcf_escape_string_raw(mpc_val_t *x);
229 | mpc_val_t *mpcf_escape_char_raw(mpc_val_t *x);
230 |
231 | mpc_val_t *mpcf_unescape(mpc_val_t *x);
232 | mpc_val_t *mpcf_unescape_regex(mpc_val_t *x);
233 | mpc_val_t *mpcf_unescape_string_raw(mpc_val_t *x);
234 | mpc_val_t *mpcf_unescape_char_raw(mpc_val_t *x);
235 |
236 | mpc_val_t *mpcf_null(int n, mpc_val_t** xs);
237 | mpc_val_t *mpcf_fst(int n, mpc_val_t** xs);
238 | mpc_val_t *mpcf_snd(int n, mpc_val_t** xs);
239 | mpc_val_t *mpcf_trd(int n, mpc_val_t** xs);
240 |
241 | mpc_val_t *mpcf_fst_free(int n, mpc_val_t** xs);
242 | mpc_val_t *mpcf_snd_free(int n, mpc_val_t** xs);
243 | mpc_val_t *mpcf_trd_free(int n, mpc_val_t** xs);
244 |
245 | mpc_val_t *mpcf_strfold(int n, mpc_val_t** xs);
246 | mpc_val_t *mpcf_maths(int n, mpc_val_t** xs);
247 |
248 | /*
249 | ** Regular Expression Parsers
250 | */
251 |
252 | mpc_parser_t *mpc_re(const char *re);
253 |
254 | /*
255 | ** AST
256 | */
257 |
258 | typedef struct mpc_ast_t {
259 | char *tag;
260 | char *contents;
261 | mpc_state_t state;
262 | int children_num;
263 | struct mpc_ast_t** children;
264 | } mpc_ast_t;
265 |
266 | mpc_ast_t *mpc_ast_new(const char *tag, const char *contents);
267 | mpc_ast_t *mpc_ast_build(int n, const char *tag, ...);
268 | mpc_ast_t *mpc_ast_add_root(mpc_ast_t *a);
269 | mpc_ast_t *mpc_ast_add_child(mpc_ast_t *r, mpc_ast_t *a);
270 | mpc_ast_t *mpc_ast_add_tag(mpc_ast_t *a, const char *t);
271 | mpc_ast_t *mpc_ast_tag(mpc_ast_t *a, const char *t);
272 | mpc_ast_t *mpc_ast_state(mpc_ast_t *a, mpc_state_t s);
273 |
274 | void mpc_ast_delete(mpc_ast_t *a);
275 | void mpc_ast_print(mpc_ast_t *a);
276 | void mpc_ast_print_to(mpc_ast_t *a, FILE *fp);
277 |
278 | /*
279 | ** Warning: This function currently doesn't test for equality of the `state` member!
280 | */
281 | int mpc_ast_eq(mpc_ast_t *a, mpc_ast_t *b);
282 |
283 | mpc_val_t *mpcf_fold_ast(int n, mpc_val_t **as);
284 | mpc_val_t *mpcf_str_ast(mpc_val_t *c);
285 | mpc_val_t *mpcf_state_ast(int n, mpc_val_t **xs);
286 |
287 | mpc_parser_t *mpca_tag(mpc_parser_t *a, const char *t);
288 | mpc_parser_t *mpca_add_tag(mpc_parser_t *a, const char *t);
289 | mpc_parser_t *mpca_root(mpc_parser_t *a);
290 | mpc_parser_t *mpca_state(mpc_parser_t *a);
291 | mpc_parser_t *mpca_total(mpc_parser_t *a);
292 |
293 | mpc_parser_t *mpca_not(mpc_parser_t *a);
294 | mpc_parser_t *mpca_maybe(mpc_parser_t *a);
295 |
296 | mpc_parser_t *mpca_many(mpc_parser_t *a);
297 | mpc_parser_t *mpca_many1(mpc_parser_t *a);
298 | mpc_parser_t *mpca_count(int n, mpc_parser_t *a);
299 |
300 | mpc_parser_t *mpca_or(int n, ...);
301 | mpc_parser_t *mpca_and(int n, ...);
302 |
303 | enum {
304 | MPCA_LANG_DEFAULT = 0,
305 | MPCA_LANG_PREDICTIVE = 1,
306 | MPCA_LANG_WHITESPACE_SENSITIVE = 2
307 | };
308 |
309 | mpc_parser_t *mpca_grammar(int flags, const char *grammar, ...);
310 |
311 | mpc_err_t *mpca_lang(int flags, const char *language, ...);
312 | mpc_err_t *mpca_lang_file(int flags, FILE *f, ...);
313 | mpc_err_t *mpca_lang_pipe(int flags, FILE *f, ...);
314 | mpc_err_t *mpca_lang_contents(int flags, const char *filename, ...);
315 |
316 | /*
317 | ** Misc
318 | */
319 |
320 |
321 | void mpc_print(mpc_parser_t *p);
322 | void mpc_optimise(mpc_parser_t *p);
323 | void mpc_stats(mpc_parser_t *p);
324 |
325 | int mpc_test_pass(mpc_parser_t *p, const char *s, const void *d,
326 | int(*tester)(const void*, const void*),
327 | mpc_dtor_t destructor,
328 | void(*printer)(const void*));
329 |
330 | int mpc_test_fail(mpc_parser_t *p, const char *s, const void *d,
331 | int(*tester)(const void*, const void*),
332 | mpc_dtor_t destructor,
333 | void(*printer)(const void*));
334 |
335 |
336 |
337 | #endif
--------------------------------------------------------------------------------
/built_in.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Mohamed Rashad
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * adouble with this program. If not, see .
16 | */
17 |
18 |
19 | #ifndef BUILT_IN_H
20 | #define BUILT_IN_H
21 |
22 | /* Builtins */
23 |
24 | #define LASSERT(args, cond, fmt, ...) \
25 | if (!(cond)) { smplx_val* err = smplx_val_err(fmt, ##__VA_ARGS__); smplx_val_del(args); return err; }
26 |
27 | #define LASSERT_TYPE(func, args, index, expect) \
28 | LASSERT(args, args->cell[index]->type == expect, \
29 | "Function '%s' passed incorrect type for argument %i. Got %s, Expected %s.", \
30 | func, index, ltype_name(args->cell[index]->type), ltype_name(expect))
31 |
32 | #define LASSERT_NUM(func, args, num) \
33 | LASSERT(args, args->count == num, \
34 | "Function '%s' passed incorrect number of arguments. Got %i, Expected %i.", \
35 | func, args->count, num)
36 |
37 | #define LASSERT_NOT_EMPTY(func, args, index) \
38 | LASSERT(args, args->cell[index]->count != 0, \
39 | "Function '%s' passed {} for argument %i.", func, index);
40 |
41 | smplx_val* smplx_val_eval(smplx_scope* e, smplx_val* v);
42 |
43 | smplx_val* builtin_lambda(smplx_scope* e, smplx_val* a) {
44 | LASSERT_NUM("@", a, 2);
45 | LASSERT_TYPE("@", a, 0, LVAL_QEXPR);
46 | LASSERT_TYPE("@", a, 1, LVAL_QEXPR);
47 |
48 | for (int i = 0; i < a->cell[0]->count; i++) {
49 | LASSERT(a, (a->cell[0]->cell[i]->type == LVAL_SYM),
50 | "Cannot define non-symbol. Got %s, Expected %s.",
51 | ltype_name(a->cell[0]->cell[i]->type), ltype_name(LVAL_SYM));
52 | }
53 |
54 | smplx_val* formals = smplx_val_pop(a, 0);
55 | smplx_val* body = smplx_val_pop(a, 0);
56 | smplx_val_del(a);
57 |
58 | return smplx_val_lambda(formals, body);
59 | }
60 |
61 | smplx_val* builtin_list(smplx_scope* e, smplx_val* a) {
62 | a->type = LVAL_QEXPR;
63 | return a;
64 | }
65 |
66 | smplx_val* builtin_head(smplx_scope* e, smplx_val* a) {
67 | LASSERT_NUM("head", a, 1);
68 | LASSERT_TYPE("head", a, 0, LVAL_QEXPR);
69 | LASSERT_NOT_EMPTY("head", a, 0);
70 |
71 | smplx_val* v = smplx_val_take(a, 0);
72 | while (v->count > 1) {
73 | smplx_val_del(smplx_val_pop(v, 1));
74 | }
75 | return v;
76 | }
77 |
78 | smplx_val* builtin_tail(smplx_scope* e, smplx_val* a) {
79 | LASSERT_NUM("tail", a, 1);
80 | LASSERT_TYPE("tail", a, 0, LVAL_QEXPR);
81 | LASSERT_NOT_EMPTY("tail", a, 0);
82 |
83 | smplx_val* v = smplx_val_take(a, 0);
84 | smplx_val_del(smplx_val_pop(v, 0));
85 | return v;
86 | }
87 |
88 | smplx_val* builtin_eval(smplx_scope* e, smplx_val* a) {
89 | LASSERT_NUM("eval", a, 1);
90 | LASSERT_TYPE("eval", a, 0, LVAL_QEXPR);
91 |
92 | smplx_val* x = smplx_val_take(a, 0);
93 | x->type = LVAL_SEXPR;
94 | return smplx_val_eval(e, x);
95 | }
96 |
97 | smplx_val* builtin_join(smplx_scope* e, smplx_val* a) {
98 |
99 | for (int i = 0; i < a->count; i++) {
100 | LASSERT_TYPE("join", a, i, LVAL_QEXPR);
101 | }
102 |
103 | smplx_val* x = smplx_val_pop(a, 0);
104 |
105 | while (a->count) {
106 | smplx_val* y = smplx_val_pop(a, 0);
107 | x = smplx_val_join(x, y);
108 | }
109 |
110 | smplx_val_del(a);
111 | return x;
112 | }
113 |
114 | smplx_val* builtin_op(smplx_scope* e, smplx_val* a, char* op) {
115 |
116 | for (int i = 0; i < a->count; i++) {
117 | LASSERT_TYPE(op, a, i, LVAL_NUM);
118 | }
119 |
120 | smplx_val* x = smplx_val_pop(a, 0);
121 |
122 | if ((strcmp(op, "-") == 0) && a->count == 0) {
123 | x->num = -x->num;
124 | }
125 |
126 | while (a->count > 0) {
127 | smplx_val* y = smplx_val_pop(a, 0);
128 |
129 | if (strcmp(op, "+") == 0) {
130 | x->num += y->num;
131 | }
132 | if (strcmp(op, "-") == 0) {
133 | x->num -= y->num;
134 | }
135 | if (strcmp(op, "*") == 0) {
136 | x->num *= y->num;
137 | }
138 | if (strcmp(op, "/") == 0) {
139 | if (y->num == 0) {
140 | smplx_val_del(x);
141 | smplx_val_del(y);
142 | x = smplx_val_err("Division By Zero.");
143 | break;
144 | }
145 | x->num /= y->num;
146 | }
147 |
148 | smplx_val_del(y);
149 | }
150 |
151 | smplx_val_del(a);
152 | return x;
153 | }
154 |
155 | smplx_val* builtin_add(smplx_scope* e, smplx_val* a) {
156 | return builtin_op(e, a, "+");
157 | }
158 |
159 | smplx_val* builtin_sub(smplx_scope* e, smplx_val* a) {
160 | return builtin_op(e, a, "-");
161 | }
162 |
163 | smplx_val* builtin_mul(smplx_scope* e, smplx_val* a) {
164 | return builtin_op(e, a, "*");
165 | }
166 |
167 | smplx_val* builtin_div(smplx_scope* e, smplx_val* a) {
168 | return builtin_op(e, a, "/");
169 | }
170 |
171 | smplx_val* builtin_var(smplx_scope* e, smplx_val* a, char* func) {
172 | LASSERT_TYPE(func, a, 0, LVAL_QEXPR);
173 |
174 | smplx_val* syms = a->cell[0];
175 | for (int i = 0; i < syms->count; i++) {
176 | LASSERT(a, (syms->cell[i]->type == LVAL_SYM),
177 | "Function '%s' cannot define non-symbol. "
178 | "Got %s, Expected %s.",
179 | func, ltype_name(syms->cell[i]->type), ltype_name(LVAL_SYM));
180 | }
181 |
182 | LASSERT(a, (syms->count == a->count - 1),
183 | "Function '%s' passed too many arguments for symbols. "
184 | "Got %i, Expected %i.",
185 | func, syms->count, a->count - 1);
186 |
187 | for (int i = 0; i < syms->count; i++) {
188 | if (strcmp(func, "define") == 0) {
189 | smplx_scope_def(e, syms->cell[i], a->cell[i + 1]);
190 | }
191 | if (strcmp(func, "=") == 0) {
192 | smplx_scope_put(e, syms->cell[i], a->cell[i + 1]);
193 | }
194 | }
195 |
196 | smplx_val_del(a);
197 | return smplx_val_sexpr();
198 | }
199 |
200 | smplx_val* builtin_def(smplx_scope* e, smplx_val* a) {
201 | return builtin_var(e, a, "define");
202 | }
203 |
204 | smplx_val* builtin_put(smplx_scope* e, smplx_val* a) {
205 | return builtin_var(e, a, "let");
206 | }
207 |
208 | smplx_val* builtin_ord(smplx_scope* e, smplx_val* a, char* op) {
209 | LASSERT_NUM(op, a, 2);
210 | LASSERT_TYPE(op, a, 0, LVAL_NUM);
211 | LASSERT_TYPE(op, a, 1, LVAL_NUM);
212 |
213 | int r;
214 | if (strcmp(op, ">") == 0) {
215 | r = (a->cell[0]->num > a->cell[1]->num);
216 | }
217 | if (strcmp(op, "<") == 0) {
218 | r = (a->cell[0]->num < a->cell[1]->num);
219 | }
220 | if (strcmp(op, ">=") == 0) {
221 | r = (a->cell[0]->num >= a->cell[1]->num);
222 | }
223 | if (strcmp(op, "<=") == 0) {
224 | r = (a->cell[0]->num <= a->cell[1]->num);
225 | }
226 | smplx_val_del(a);
227 | return smplx_val_num(r);
228 | }
229 |
230 | smplx_val* builtin_gt(smplx_scope* e, smplx_val* a) {
231 | return builtin_ord(e, a, ">");
232 | }
233 |
234 | smplx_val* builtin_lt(smplx_scope* e, smplx_val* a) {
235 | return builtin_ord(e, a, "<");
236 | }
237 |
238 | smplx_val* builtin_ge(smplx_scope* e, smplx_val* a) {
239 | return builtin_ord(e, a, ">=");
240 | }
241 |
242 | smplx_val* builtin_le(smplx_scope* e, smplx_val* a) {
243 | return builtin_ord(e, a, "<=");
244 | }
245 |
246 | smplx_val* builtin_cmp(smplx_scope* e, smplx_val* a, char* op) {
247 | LASSERT_NUM(op, a, 2);
248 | int r;
249 | if (strcmp(op, "==") == 0) {
250 | r = smplx_val_eq(a->cell[0], a->cell[1]);
251 | }
252 | if (strcmp(op, "!=") == 0) {
253 | r = !smplx_val_eq(a->cell[0], a->cell[1]);
254 | }
255 | smplx_val_del(a);
256 | return smplx_val_num(r);
257 | }
258 |
259 | smplx_val* builtin_eq(smplx_scope* e, smplx_val* a) {
260 | return builtin_cmp(e, a, "==");
261 | }
262 |
263 | smplx_val* builtin_ne(smplx_scope* e, smplx_val* a) {
264 | return builtin_cmp(e, a, "!=");
265 | }
266 |
267 | smplx_val* builtin_if(smplx_scope* e, smplx_val* a) {
268 | LASSERT_NUM("if", a, 3);
269 | LASSERT_TYPE("if", a, 0, LVAL_NUM);
270 | LASSERT_TYPE("if", a, 1, LVAL_QEXPR);
271 | LASSERT_TYPE("if", a, 2, LVAL_QEXPR);
272 |
273 | smplx_val* x;
274 | a->cell[1]->type = LVAL_SEXPR;
275 | a->cell[2]->type = LVAL_SEXPR;
276 |
277 | if (a->cell[0]->num) {
278 | x = smplx_val_eval(e, smplx_val_pop(a, 1));
279 | } else {
280 | x = smplx_val_eval(e, smplx_val_pop(a, 2));
281 | }
282 |
283 | smplx_val_del(a);
284 | return x;
285 | }
286 |
287 | smplx_val* smplx_val_read(mpc_ast_t* t);
288 |
289 | ////////////////////////////////////////////////////////////////////////////////////////////////////////
290 |
291 | smplx_val* builtin_load(smplx_scope* e, smplx_val* a) {
292 | LASSERT_NUM("load", a, 1);
293 | LASSERT_TYPE("load", a, 0, LVAL_STR);
294 |
295 | /* Parse File given by string name */
296 |
297 | mpc_result_t r;
298 | if (mpc_parse_contents(a->cell[0]->str, Lispy, &r)) {
299 |
300 | smplx_val* expr = smplx_val_read(r.output);
301 |
302 | smplx_val* x = smplx_val_eval(e, expr);
303 | smplx_val_println(x);
304 | smplx_val_del(x);
305 |
306 | mpc_ast_delete(r.output);
307 |
308 | return smplx_val_sexpr();
309 |
310 | } else {
311 | /* Get Parse Error as String */
312 | char* err_msg = mpc_err_string(r.error);
313 | mpc_err_delete(r.error);
314 |
315 | /* Create new error message using it */
316 | smplx_val* err = smplx_val_err("Could not load Library %s", err_msg);
317 | free(err_msg);
318 | smplx_val_del(a);
319 |
320 | /* Cleanup and return error */
321 | return err;
322 | }
323 |
324 | }
325 |
326 |
327 |
328 |
329 | ////////////////////////////////////////////////////////////////////////////////////////////////////////
330 |
331 | smplx_val* builtin_scan(smplx_scope* e, smplx_val* a) {
332 |
333 | char input[1000];
334 | FILE *fptr;
335 |
336 | fptr = fopen("define.sx", "w");
337 |
338 | if (fptr == NULL) {
339 | printf("Error!");
340 | }
341 |
342 |
343 | fgets(input, 1000, stdin);
344 | fprintf(fptr, "(define [%s] %s)", a->cell[0]->str, input);
345 | fclose(fptr);
346 |
347 |
348 | mpc_result_t r;
349 | if (mpc_parse_contents("define.sx", Lispy, &r)) {
350 |
351 | smplx_val* expr = smplx_val_read(r.output);
352 |
353 | smplx_val* x = smplx_val_eval(e, expr);
354 | smplx_val_println(x);
355 | smplx_val_del(x);
356 |
357 | mpc_ast_delete(r.output);
358 |
359 | return smplx_val_sexpr();
360 |
361 | } else {
362 | /* Get Parse Error as String */
363 | char* err_msg = mpc_err_string(r.error);
364 | mpc_err_delete(r.error);
365 |
366 | /* Create new error message using it */
367 | smplx_val* err = smplx_val_err("Could not load Library %s", err_msg);
368 | free(err_msg);
369 | smplx_val_del(a);
370 |
371 | /* Cleanup and return error */
372 | return err;
373 | }
374 |
375 | }
376 |
377 | smplx_val* builtin_print(smplx_scope* e, smplx_val* a) {
378 |
379 | /* Print each argument followed by a space */
380 | for (int i = 0; i < a->count; i++) {
381 | smplx_val_print(a->cell[i]);
382 | putchar(' ');
383 | }
384 |
385 | /* Print a newline and delete arguments */
386 | putchar('\n');
387 | smplx_val_del(a);
388 |
389 | return smplx_val_sexpr();
390 | }
391 |
392 | smplx_val* builtin_error(smplx_scope* e, smplx_val* a) {
393 | LASSERT_NUM("error", a, 1);
394 | LASSERT_TYPE("error", a, 0, LVAL_STR);
395 |
396 | /* Construct Error from first argument */
397 | smplx_val* err = smplx_val_err(a->cell[0]->str);
398 |
399 | /* Delete arguments and return */
400 | smplx_val_del(a);
401 | return err;
402 | }
403 |
404 | void smplx_scope_add_builtin(smplx_scope* e, char* name, lbuiltin func) {
405 | smplx_val* k = smplx_val_sym(name);
406 | smplx_val* v = smplx_val_builtin(func);
407 | smplx_scope_put(e, k, v);
408 | smplx_val_del(k);
409 | smplx_val_del(v);
410 | }
411 |
412 | void smplx_scope_add_builtins(smplx_scope* e) {
413 | /* Variable Functions */
414 | smplx_scope_add_builtin(e, "@", builtin_lambda);
415 | smplx_scope_add_builtin(e, "define", builtin_def);
416 | smplx_scope_add_builtin(e, "let", builtin_put);
417 |
418 | /* List Functions */
419 | smplx_scope_add_builtin(e, "list", builtin_list);
420 | smplx_scope_add_builtin(e, "head", builtin_head);
421 | smplx_scope_add_builtin(e, "tail", builtin_tail);
422 | smplx_scope_add_builtin(e, "eval", builtin_eval);
423 | smplx_scope_add_builtin(e, "join", builtin_join);
424 |
425 | /* Mathematical Functions */
426 | smplx_scope_add_builtin(e, "+", builtin_add);
427 | smplx_scope_add_builtin(e, "-", builtin_sub);
428 | smplx_scope_add_builtin(e, "*", builtin_mul);
429 | smplx_scope_add_builtin(e, "/", builtin_div);
430 |
431 | /* Comparison Functions */
432 | smplx_scope_add_builtin(e, "if", builtin_if);
433 | smplx_scope_add_builtin(e, "==", builtin_eq);
434 | smplx_scope_add_builtin(e, "!=", builtin_ne);
435 | smplx_scope_add_builtin(e, ">", builtin_gt);
436 | smplx_scope_add_builtin(e, "<", builtin_lt);
437 | smplx_scope_add_builtin(e, ">=", builtin_ge);
438 | smplx_scope_add_builtin(e, "<=", builtin_le);
439 |
440 | /* String Functions */
441 | smplx_scope_add_builtin(e, "load", builtin_load);
442 | smplx_scope_add_builtin(e, "error", builtin_error);
443 | smplx_scope_add_builtin(e, "print", builtin_print);
444 | smplx_scope_add_builtin(e, "scan", builtin_scan);
445 |
446 | }
447 |
448 |
449 | #endif /* BUILT_IN_H */
450 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 | {one line to give the program's name and a brief idea of what it does.}
635 | Copyright (C) {year} {name of author}
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | {project} Copyright (C) {year} {fullname}
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------