Project

General

Profile

Defect #761 ยป install.patch

Florian Negele, 11 August 2026 23:34

View differences:

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&);
};
    (1-1/1)