Defect #761 ยป install.patch
| makefile | ||
|---|---|---|
|
commonflags := -c -pipe -x c++ -std=c++17 --pedantic -Wfatal-errors
|
||
|
cflags = $(commonflags) -Werror -Wall -Wextra -Wmissing-noreturn -Wno-switch -Wno-empty-body -Wno-parentheses -Wzero-as-null-pointer-constant -Wno-missing-field-initializers -Wno-return-type -Wno-misleading-indentation -Wno-psabi -Wno-implicit-fallthrough -Wno-suggest-attribute=noreturn -o $(notdir $@)
|
||
|
cflags = $(commonflags) -Werror -Wall -Wextra -Wmissing-noreturn -Wno-switch -Wno-empty-body -Wno-parentheses -Wzero-as-null-pointer-constant -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-return-type -Wno-misleading-indentation -Wno-psabi -Wno-implicit-fallthrough -Wno-suggest-attribute=noreturn -o $(notdir $@)
|
||
|
lflags = -o $(notdir $@)
|
||
|
ccheckflags := $(commonflags) -fsyntax-only
|
||
| ... | ... | |
|
lib := $(addprefix $(runtime), $(addsuffix run.lib, $(addprefix cpp, $(targets)) $(addprefix ob, $(targets))))
|
||
|
std := $(addprefix $(cpplibrary), cassert.cpp cctype.cpp cmath.cpp csetjmp.cpp cstdio.cpp cstdlib.cpp cstring.cpp ctime.cpp debugging.cpp exception.cpp)
|
||
|
hdr := $(addprefix $(cpplibrary), algorithm any array assert.h atomic barrier bit bitset cassert cctype cerrno cfenv cfloat charconv chrono cinttypes climits clocale cmath codecvt compare complex complex.h concepts condition_variable coroutine csetjmp csignal cstdarg cstddef cstdint cstdio cstdlib cstring ctime ctype.h cuchar cwchar cwctype debugging deque errno.h exception execution expected fenv.h filesystem flat_map flat_set float.h format forward_list fstream functional future generator initializer_list inttypes.h iomanip ios iosfwd iostream iso646.h istream iterator latch limits limits.h list locale locale.h map math.h mdspan memory memory_resource mutex new numbers numeric optional ostream print queue random ranges ratio rcu regex scoped_allocator semaphore set setjmp.h shared_mutex signal.h source_location span spanstream sstream stack stacktrace stdalign.h stdarg.h stdatomic.h stdbool.h stddef.h stdexcept stdfloat stdint.h stdio.h stdlib.h stop_token streambuf string string.h string_view strstream syncstream system_error text_encoding tgmath.h thread time.h tuple type_traits typeindex typeinfo uchar.h unordered_map unordered_set utility valarray variant vector version wchar.h wctype.h)
|
||
|
api := $(addprefix $(apilibrary), darwin.hpp dlfcn.h linux.hpp pthread.h SDL.h tos.h windows.h)
|
||
|
def := $(addprefix $(deflibrary), assembly darwinlib elf linuxlib macho pe tos wasm wasmlib winlib)
|
||
|
api := $(addprefix $(apilibrary), darwin.hpp dlfcn.h efi.h linux.hpp pthread.h SDL.h tos.h windows.h)
|
||
|
def := $(addprefix $(deflibrary), assembly darwinlib efi elf linuxlib macho pe tos wasm wasmlib winlib)
|
||
|
obl := $(addprefix $(oblibrary), obl.arguments.mod obl.hashes.mod obl.basictypes.mod obl.booleans.mod obl.characters.mod obl.devices.mod obl.environment.mod obl.exceptions.mod obl.files.mod obl.iostreams.mod obl.streams.mod obl.iterators.mod obl.arrays.mod obl.coroutines.mod obl.dynamicarrays.mod obl.generators.mod obl.lists.mod obl.pairs.mod obl.hashmaps.mod obl.functions.mod obl.in.mod obl.math.mod obl.out.mod obl.random.mod obl.sets.mod obl.strings.mod obl.trees.mod)
|
||
|
ext := $(addprefix $(oblibrary), api.darwin.mod api.linux.mod api.pthread.mod api.sdl.mod api.tos.mod api.windows.mod)
|
||
|
oak := $(addprefix $(oblibrary), coroutines.mod in.mod math.mod mathc.mod mathl.mod mathlc.mod out.mod strings.mod xyplane.mod)
|
||
| ... | ... | |
|
man1dir := $(mandir)/man1
|
||
|
docdir := $(prefix)/share/doc/ecs
|
||
|
install: uninstall
|
||
|
@mkdir -p $(DESTDIR)$(ecsdir)
|
||
|
@mkdir -p $(DESTDIR)$(ecsdir)/$(tools)
|
||
|
@cp $(filter $(toolsp)%, $(wildcard $(bin))) $(DESTDIR)$(ecsdir)/$(tools)
|
||
|
@mkdir -p $(DESTDIR)$(ecsdir)/$(runtime)
|
||
|
@cp $(wildcard $(obf) $(run) $(lib) $(cod)) $(DESTDIR)$(ecsdir)/$(runtime)
|
||
|
@mkdir -p $(DESTDIR)$(ecsdir)/$(cpplibrary)
|
||
|
@cp $(hdr) $(DESTDIR)$(ecsdir)/$(cpplibrary)
|
||
|
@mkdir -p $(DESTDIR)$(ecsdir)/$(oblibrary)
|
||
|
@cp $(wildcard $(sym)) $(DESTDIR)$(ecsdir)/$(oblibrary)
|
||
|
@mkdir -p $(DESTDIR)$(ecsdir)/$(utilities)
|
||
|
@cp $(utilities)ecsd $(DESTDIR)$(ecsdir)/$(utilities)
|
||
|
@mkdir -p $(DESTDIR)$(bindir)
|
||
|
@ln -s $(patsubst $(DESTDIR)$(prefix)/%,../%,$(DESTDIR)$(ecsdir))/$(utilities)ecsd $(DESTDIR)$(bindir)/ecsd
|
||
|
@mkdir -p $(DESTDIR)$(man1dir)
|
||
|
@cp $(documentation)ecsd.1 $(DESTDIR)$(man1dir)/ecsd.1
|
||
|
@mkdir -p $(DESTDIR)$(docdir)
|
||
|
@cp $(wildcard $(pdf)) $(DESTDIR)$(docdir)
|
||
|
install: uninstall $(utilities)ecsd$(prg)
|
||
|
@test -z "$(filter $(toolsp)%, $(wildcard $(bin)))" || install -D -t $(DESTDIR)$(ecsdir)/$(tools) $(filter $(toolsp)%, $(wildcard $(bin)))
|
||
|
@test -z "$(wildcard $(obf) $(run) $(lib) $(cod))" || install -D -t $(DESTDIR)$(ecsdir)/$(runtime) $(wildcard $(obf) $(run) $(lib) $(cod))
|
||
|
@install -D -t $(DESTDIR)$(ecsdir)/$(cpplibrary) $(hdr)
|
||
|
@install -D -t $(DESTDIR)$(ecsdir)/$(apilibrary) $(api)
|
||
|
@install -D -t $(DESTDIR)$(ecsdir)/$(deflibrary) $(def)
|
||
|
@test -z "$(wildcard $(sym))" || install -D -t $(DESTDIR)$(ecsdir)/$(oblibrary) $(wildcard $(sym))
|
||
|
@install -D -t $(DESTDIR)$(ecsdir)/$(utilities) $(utilities)ecsd$(prg)
|
||
|
@install -d $(DESTDIR)$(bindir)
|
||
|
@ln -s $(abspath $(DESTDIR)$(ecsdir)/$(utilities)ecsd$(prg)) $(DESTDIR)$(bindir)/ecsd
|
||
|
@install -D -t $(DESTDIR)$(man1dir) $(documentation)ecsd.1
|
||
|
@test -z "$(wildcard $(pdf))" || install -D -t $(DESTDIR)$(docdir) $(wildcard $(pdf))
|
||
|
uninstall:
|
||
|
@rm -f -r $(DESTDIR)$(ecsdir)
|
||
| tools/falinterpreter.cpp | ||
|---|---|---|
|
void Interpret (const Element&);
|
||
|
void Push (const Value&);
|
||
|
Value Pop (const Element&);
|
||
|
Integer PopInteger (const Element&);
|
||
|
Value& PopVariable (const Element&);
|
||
|
const Function& PopFunction (const Element&);
|
||
|
Value Pop (const Position&);
|
||
|
Integer PopInteger (const Position&);
|
||
|
Value& PopVariable (const Position&);
|
||
|
const Function& PopFunction (const Position&);
|
||
|
void EmitError [[noreturn]] (const Element&, const char*) const;
|
||
|
void EmitError [[noreturn]] (const Position&, const char*) const;
|
||
|
};
|
||
|
struct Context::Value
|
||
| ... | ... | |
|
Integer Context::Interpret (const Program& program)
|
||
|
{
|
||
|
source = &program.source; Push (0); Interpret (program.main); return PopInteger (program.main.back ());
|
||
|
source = &program.source; Push (0); Interpret (program.main); return PopInteger (program.end);
|
||
|
}
|
||
|
void Context::Interpret (const Function& function)
|
||
| ... | ... | |
|
{
|
||
|
switch (element.symbol)
|
||
|
{
|
||
|
case Lexer::Assign: {auto& variable = PopVariable (element); variable = Pop (element); break;}
|
||
|
case Lexer::Call: Interpret (PopFunction (element)); break;
|
||
|
case Lexer::If: {auto& function = PopFunction (element); if (PopInteger (element)) Interpret (function); break;}
|
||
|
case Lexer::While: {auto &function = PopFunction (element), &condition = PopFunction (element); while (Interpret (condition), PopInteger (element)) Interpret (function); break;}
|
||
|
case Lexer::Write: environment.Fputs (std::to_string (PopInteger (element)), environment.stdout_); break;
|
||
|
case Lexer::Put: environment.Putchar (PopInteger (element)); break;
|
||
|
case Lexer::Assign: {auto& variable = PopVariable (element.position); variable = Pop (element.position); break;}
|
||
|
case Lexer::Call: Interpret (PopFunction (element.position)); break;
|
||
|
case Lexer::If: {auto& function = PopFunction (element.position); if (PopInteger (element.position)) Interpret (function); break;}
|
||
|
case Lexer::While: {auto &function = PopFunction (element.position), &condition = PopFunction (element.position); while (Interpret (condition), PopInteger (element.position)) Interpret (function); break;}
|
||
|
case Lexer::Write: environment.Fputs (std::to_string (PopInteger (element.position)), environment.stdout_); break;
|
||
|
case Lexer::Put: environment.Putchar (PopInteger (element.position)); break;
|
||
|
case Lexer::Get: Push (environment.Getchar ()); break;
|
||
|
case Lexer::Flush: environment.Fflush (environment.stdout_); break;
|
||
|
case Lexer::Dereference: Push (PopVariable (element)); break;
|
||
|
case Lexer::Dereference: Push (PopVariable (element.position)); break;
|
||
|
case Lexer::BeginFunction: Push (element.function); break;
|
||
|
case Lexer::Negate: Push (-PopInteger (element)); break;
|
||
|
case Lexer::Add: {const auto value = PopInteger (element); Push (PopInteger (element) + value); break;}
|
||
|
case Lexer::Subtract: {const auto value = PopInteger (element); Push (PopInteger (element) - value); break;}
|
||
|
case Lexer::Multiply: {const auto value = PopInteger (element); Push (PopInteger (element) * value); break;}
|
||
|
case Lexer::Divide: {const auto value = PopInteger (element); Push (PopInteger (element) / value); break;}
|
||
|
case Lexer::Not: Push (!PopInteger (element)); break;
|
||
|
case Lexer::And: {const auto value = PopInteger (element); Push (PopInteger (element) && value); break;}
|
||
|
case Lexer::Or: {const auto value = PopInteger (element); Push (PopInteger (element) || value); break;}
|
||
|
case Lexer::Equal: {const auto value = Pop (element); Push (Pop (element) == value); break;}
|
||
|
case Lexer::Greater: {const auto value = PopInteger (element); Push (PopInteger (element) > value); break;}
|
||
|
case Lexer::Negate: Push (-PopInteger (element.position)); break;
|
||
|
case Lexer::Add: {const auto value = PopInteger (element.position); Push (PopInteger (element.position) + value); break;}
|
||
|
case Lexer::Subtract: {const auto value = PopInteger (element.position); Push (PopInteger (element.position) - value); break;}
|
||
|
case Lexer::Multiply: {const auto value = PopInteger (element.position); Push (PopInteger (element.position) * value); break;}
|
||
|
case Lexer::Divide: {const auto value = PopInteger (element.position); Push (PopInteger (element.position) / value); break;}
|
||
|
case Lexer::Not: Push (!PopInteger (element.position)); break;
|
||
|
case Lexer::And: {const auto value = PopInteger (element.position); Push (PopInteger (element.position) && value); break;}
|
||
|
case Lexer::Or: {const auto value = PopInteger (element.position); Push (PopInteger (element.position) || value); break;}
|
||
|
case Lexer::Equal: {const auto value = Pop (element.position); Push (Pop (element.position) == value); break;}
|
||
|
case Lexer::Greater: {const auto value = PopInteger (element.position); Push (PopInteger (element.position) > value); break;}
|
||
|
case Lexer::Duplicate: Push (stack.back ()); break;
|
||
|
case Lexer::Delete: Pop (element); break;
|
||
|
case Lexer::Swap: {const auto object1 = Pop (element), object2 = Pop (element); Push (object1); Push (object2); break;}
|
||
|
case Lexer::Rotate: {const auto object1 = Pop (element), object2 = Pop (element), object3 (Pop (element)); Push (object2); Push (object1); Push (object3); break;}
|
||
|
case Lexer::Select: {const auto selection = PopInteger (element); if (selection >= Integer (stack.size ())) EmitError (element, "invalid selection"); Push (stack[stack.size () - selection - 1]); break;}
|
||
|
case Lexer::Delete: Pop (element.position); break;
|
||
|
case Lexer::Swap: {const auto object1 = Pop (element.position), object2 = Pop (element.position); Push (object1); Push (object2); break;}
|
||
|
case Lexer::Rotate: {const auto object1 = Pop (element.position), object2 = Pop (element.position), object3 (Pop (element.position)); Push (object2); Push (object1); Push (object3); break;}
|
||
|
case Lexer::Select: {const auto selection = PopInteger (element.position); if (selection >= Integer (stack.size ())) EmitError (element.position, "invalid selection"); Push (stack[stack.size () - selection - 1]); break;}
|
||
|
case Lexer::Integer: Push (element.integer); break;
|
||
|
case Lexer::Character: Push (Integer (element.character)); break;
|
||
|
case Lexer::Variable: Push (&variables[element.character - 'a']); break;
|
||
|
case Lexer::String: environment.Fputs (element.string, environment.stdout_); break;
|
||
|
case Lexer::ExternalVariable: EmitError (element, "extern variables not supported");
|
||
|
case Lexer::ExternalFunction: EmitError (element, "extern functions not supported");
|
||
|
case Lexer::Assembly: EmitError (element, "inline assembly not supported");
|
||
|
case Lexer::ExternalVariable: EmitError (element.position, "extern variables not supported");
|
||
|
case Lexer::ExternalFunction: EmitError (element.position, "extern functions not supported");
|
||
|
case Lexer::Assembly: EmitError (element.position, "inline assembly not supported");
|
||
|
default: assert (Lexer::Unreachable);
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
stack.push_back (value);
|
||
|
}
|
||
|
Context::Value Context::Pop (const Element& element)
|
||
|
Context::Value Context::Pop (const Position& position)
|
||
|
{
|
||
|
if (stack.empty ()) EmitError (element, "stack empty");
|
||
|
if (stack.empty ()) EmitError (position, "stack empty");
|
||
|
const auto value = stack.back (); stack.pop_back (); return value;
|
||
|
}
|
||
|
Integer Context::PopInteger (const Element& element)
|
||
|
Integer Context::PopInteger (const Position& position)
|
||
|
{
|
||
|
const auto value = Pop (element); if (value.type != Value::Integer) EmitError (element, "stack top not an integer"); return value.integer;
|
||
|
const auto value = Pop (position); if (value.type != Value::Integer) EmitError (position, "stack top not an integer"); return value.integer;
|
||
|
}
|
||
|
Context::Value& Context::PopVariable (const Element& element)
|
||
|
Context::Value& Context::PopVariable (const Position& position)
|
||
|
{
|
||
|
const auto value = Pop (element); if (value.type != Value::Variable) EmitError (element, "stack top not a variable"); return *value.variable;
|
||
|
const auto value = Pop (position); if (value.type != Value::Variable) EmitError (position, "stack top not a variable"); return *value.variable;
|
||
|
}
|
||
|
const Function& Context::PopFunction (const Element& element)
|
||
|
const Function& Context::PopFunction (const Position& position)
|
||
|
{
|
||
|
const auto value = Pop (element); if (value.type != Value::Function) EmitError (element, "stack top not a function"); return *value.function;
|
||
|
const auto value = Pop (position); if (value.type != Value::Function) EmitError (position, "stack top not a function"); return *value.function;
|
||
|
}
|
||
|
void Context::EmitError (const Element& element, const char*const message) const
|
||
|
void Context::EmitError (const Position& position, const char*const message) const
|
||
|
{
|
||
|
interpreter.diagnostics.Emit (Diagnostics::Error, *source, element.position, message); throw Error {};
|
||
|
interpreter.diagnostics.Emit (Diagnostics::Error, *source, position, message); throw Error {};
|
||
|
}
|
||
|
Context::Value::Value (const FALSE::Integer i) :
|
||
| tools/falparser.cpp | ||
|---|---|---|
|
}
|
||
|
if (!stack.empty ()) EmitError (program, current.position, "function not closed");
|
||
|
program.end = current.position;
|
||
|
}
|
||
| tools/false.hpp | ||
|---|---|---|
|
{
|
||
|
Source source;
|
||
|
Function main;
|
||
|
Position end;
|
||
|
explicit Program (const Source&);
|
||
|
};
|
||