Merge pull request 'develop' (#8) from develop into master

Reviewed-on: #8
This commit is contained in:
Chris Cromer 2022-11-29 00:09:37 -03:00
commit 69aec1689c
36 changed files with 1213 additions and 156 deletions

View File

@ -1,61 +1,97 @@
[
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/obelisk.cpp.o -MF src/obelisk.p/obelisk.cpp.o.d -o src/obelisk.p/obelisk.cpp.o -c ../src/obelisk.cpp",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/obelisk.cpp.o -MF src/obelisk.p/obelisk.cpp.o.d -o src/obelisk.p/obelisk.cpp.o -c ../src/obelisk.cpp",
"file": "../src/obelisk.cpp",
"output": "src/obelisk.p/obelisk.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/lexer.cpp.o -MF src/obelisk.p/lexer.cpp.o.d -o src/obelisk.p/lexer.cpp.o -c ../src/lexer.cpp",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/lexer.cpp.o -MF src/obelisk.p/lexer.cpp.o.d -o src/obelisk.p/lexer.cpp.o -c ../src/lexer.cpp",
"file": "../src/lexer.cpp",
"output": "src/obelisk.p/lexer.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/parser.cpp.o -MF src/obelisk.p/parser.cpp.o.d -o src/obelisk.p/parser.cpp.o -c ../src/parser.cpp",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/parser.cpp.o -MF src/obelisk.p/parser.cpp.o.d -o src/obelisk.p/parser.cpp.o -c ../src/parser.cpp",
"file": "../src/parser.cpp",
"output": "src/obelisk.p/parser.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/knowledge_base.cpp.o -MF src/obelisk.p/knowledge_base.cpp.o.d -o src/obelisk.p/knowledge_base.cpp.o -c ../src/knowledge_base.cpp",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/knowledge_base.cpp.o -MF src/obelisk.p/knowledge_base.cpp.o.d -o src/obelisk.p/knowledge_base.cpp.o -c ../src/knowledge_base.cpp",
"file": "../src/knowledge_base.cpp",
"output": "src/obelisk.p/knowledge_base.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_action.cpp.o -MF src/obelisk.p/models_action.cpp.o.d -o src/obelisk.p/models_action.cpp.o -c ../src/models/action.cpp",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/ast_call_expression_ast.cpp.o -MF src/obelisk.p/ast_call_expression_ast.cpp.o.d -o src/obelisk.p/ast_call_expression_ast.cpp.o -c ../src/ast/call_expression_ast.cpp",
"file": "../src/ast/call_expression_ast.cpp",
"output": "src/obelisk.p/ast_call_expression_ast.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/ast_error.cpp.o -MF src/obelisk.p/ast_error.cpp.o.d -o src/obelisk.p/ast_error.cpp.o -c ../src/ast/error.cpp",
"file": "../src/ast/error.cpp",
"output": "src/obelisk.p/ast_error.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/ast_function_ast.cpp.o -MF src/obelisk.p/ast_function_ast.cpp.o.d -o src/obelisk.p/ast_function_ast.cpp.o -c ../src/ast/function_ast.cpp",
"file": "../src/ast/function_ast.cpp",
"output": "src/obelisk.p/ast_function_ast.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/ast_number_expression_ast.cpp.o -MF src/obelisk.p/ast_number_expression_ast.cpp.o.d -o src/obelisk.p/ast_number_expression_ast.cpp.o -c ../src/ast/number_expression_ast.cpp",
"file": "../src/ast/number_expression_ast.cpp",
"output": "src/obelisk.p/ast_number_expression_ast.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/ast_prototype_ast.cpp.o -MF src/obelisk.p/ast_prototype_ast.cpp.o.d -o src/obelisk.p/ast_prototype_ast.cpp.o -c ../src/ast/prototype_ast.cpp",
"file": "../src/ast/prototype_ast.cpp",
"output": "src/obelisk.p/ast_prototype_ast.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/ast_variable_expression_ast.cpp.o -MF src/obelisk.p/ast_variable_expression_ast.cpp.o.d -o src/obelisk.p/ast_variable_expression_ast.cpp.o -c ../src/ast/variable_expression_ast.cpp",
"file": "../src/ast/variable_expression_ast.cpp",
"output": "src/obelisk.p/ast_variable_expression_ast.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/models_action.cpp.o -MF src/obelisk.p/models_action.cpp.o.d -o src/obelisk.p/models_action.cpp.o -c ../src/models/action.cpp",
"file": "../src/models/action.cpp",
"output": "src/obelisk.p/models_action.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_entity.cpp.o -MF src/obelisk.p/models_entity.cpp.o.d -o src/obelisk.p/models_entity.cpp.o -c ../src/models/entity.cpp",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/models_entity.cpp.o -MF src/obelisk.p/models_entity.cpp.o.d -o src/obelisk.p/models_entity.cpp.o -c ../src/models/entity.cpp",
"file": "../src/models/entity.cpp",
"output": "src/obelisk.p/models_entity.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_fact.cpp.o -MF src/obelisk.p/models_fact.cpp.o.d -o src/obelisk.p/models_fact.cpp.o -c ../src/models/fact.cpp",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/models_fact.cpp.o -MF src/obelisk.p/models_fact.cpp.o.d -o src/obelisk.p/models_fact.cpp.o -c ../src/models/fact.cpp",
"file": "../src/models/fact.cpp",
"output": "src/obelisk.p/models_fact.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_rule.cpp.o -MF src/obelisk.p/models_rule.cpp.o.d -o src/obelisk.p/models_rule.cpp.o -c ../src/models/rule.cpp",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/models_rule.cpp.o -MF src/obelisk.p/models_rule.cpp.o.d -o src/obelisk.p/models_rule.cpp.o -c ../src/models/rule.cpp",
"file": "../src/models/rule.cpp",
"output": "src/obelisk.p/models_rule.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_suggest_action.cpp.o -MF src/obelisk.p/models_suggest_action.cpp.o.d -o src/obelisk.p/models_suggest_action.cpp.o -c ../src/models/suggest_action.cpp",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/models_suggest_action.cpp.o -MF src/obelisk.p/models_suggest_action.cpp.o.d -o src/obelisk.p/models_suggest_action.cpp.o -c ../src/models/suggest_action.cpp",
"file": "../src/models/suggest_action.cpp",
"output": "src/obelisk.p/models_suggest_action.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -MD -MQ src/obelisk.p/models_verb.cpp.o -MF src/obelisk.p/models_verb.cpp.o.d -o src/obelisk.p/models_verb.cpp.o -c ../src/models/verb.cpp",
"command": "c++ -Isrc/obelisk.p -Isrc -I../src -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -isystem/usr/lib/llvm-14/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MD -MQ src/obelisk.p/models_verb.cpp.o -MF src/obelisk.p/models_verb.cpp.o.d -o src/obelisk.p/models_verb.cpp.o -c ../src/models/verb.cpp",
"file": "../src/models/verb.cpp",
"output": "src/obelisk.p/models_verb.cpp.o"
}

20
src/ast/ast.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef OBELISK_AST_AST_H
#define OBELISK_AST_AST_H
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Type.h>
#include <map>
#include <memory>
namespace obelisk
{
static std::unique_ptr<llvm::LLVMContext> TheContext;
static std::unique_ptr<llvm::Module> TheModule;
static std::unique_ptr<llvm::IRBuilder<>> Builder;
static std::map<std::string, llvm::Value *> NamedValues;
} // namespace obelisk
#endif

View File

@ -0,0 +1,31 @@
#include "ast/ast.h"
#include "ast/call_expression_ast.h"
#include "ast/error.h"
llvm::Value *obelisk::CallExpressionAST::codegen()
{
// Look up the name in the global module table.
llvm::Function *calleeF = TheModule->getFunction(callee_);
if (!calleeF)
{
return LogErrorV("Unknown function referenced");
}
// If argument mismatch error.
if (calleeF->arg_size() != args_.size())
{
return LogErrorV("Incorrect # arguments passed");
}
std::vector<llvm::Value *> argsV;
for (unsigned i = 0, e = args_.size(); i != e; ++i)
{
argsV.push_back(args_[i]->codegen());
if (!argsV.back())
{
return nullptr;
}
}
return Builder->CreateCall(calleeF, argsV, "calltmp");
}

View File

@ -28,6 +28,8 @@ namespace obelisk
args_(std::move(args))
{
}
llvm::Value *codegen() override;
};
} // namespace obelisk

13
src/ast/error.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "ast/error.h"
std::unique_ptr<obelisk::ExpressionAST> obelisk::LogError(const char *Str)
{
fprintf(stderr, "Error: %s\n", Str);
return nullptr;
}
llvm::Value *obelisk::LogErrorV(const char *Str)
{
LogError(Str);
return nullptr;
}

14
src/ast/error.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef OBELISK_AST_ERROR_H
#define OBELISK_AST_ERROR_H
#include "ast/expression_ast.h"
#include <memory>
namespace obelisk
{
std::unique_ptr<ExpressionAST> LogError(const char *Str);
llvm::Value *LogErrorV(const char *Str);
} // namespace obelisk
#endif

View File

@ -1,12 +1,15 @@
#ifndef OBELISK_AST_EXPRESSION_AST_H
#define OBELISK_AST_EXPRESSION_AST_H
#include <llvm/IR/Constants.h>
namespace obelisk
{
class ExpressionAST
{
public:
virtual ~ExpressionAST() = default;
virtual ~ExpressionAST() = default;
virtual llvm::Value *codegen() = 0;
};
} // namespace obelisk

39
src/ast/function_ast.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "ast/ast.h"
#include "ast/function_ast.h"
#include <llvm/IR/Verifier.h>
llvm::Function *obelisk::FunctionAST::codegen()
{
llvm::Function *theFunction = TheModule->getFunction(prototype_->getName());
if (!theFunction)
{
theFunction = prototype_->codegen();
}
if (!theFunction)
{
return nullptr;
}
llvm::BasicBlock *bB
= llvm::BasicBlock::Create(*TheContext, "entry", theFunction);
Builder->SetInsertPoint(bB);
NamedValues.clear();
for (auto &arg : theFunction->args())
{
NamedValues[std::string(arg.getName())] = &arg;
}
if (llvm::Value *retVal = body_->codegen())
{
Builder->CreateRet(retVal);
llvm::verifyFunction(*theFunction);
return theFunction;
}
theFunction->eraseFromParent();
return nullptr;
}

View File

@ -24,6 +24,8 @@ namespace obelisk
body_(std::move(body))
{
}
llvm::Function *codegen();
};
} // namespace obelisk

View File

@ -1,8 +1,8 @@
obelisk_ast_sources = files(
'call_expression_ast.h',
'expression_ast.h',
'function_ast.h',
'number_expression_ast.h',
'prototype_ast.h',
'variable_expression_ast.h'
'call_expression_ast.cpp',
'error.cpp',
'function_ast.cpp',
'number_expression_ast.cpp',
'prototype_ast.cpp',
'variable_expression_ast.cpp'
)

View File

@ -0,0 +1,7 @@
#include "ast/ast.h"
#include "ast/number_expression_ast.h"
llvm::Value *obelisk::NumberExpressionAST::codegen()
{
return llvm::ConstantFP::get(*TheContext, llvm::APFloat(number_));
}

View File

@ -18,6 +18,8 @@ namespace obelisk
number_(number)
{
}
llvm::Value *codegen() override;
};
} // namespace obelisk

25
src/ast/prototype_ast.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "ast/ast.h"
#include "ast/prototype_ast.h"
llvm::Function *obelisk::PrototypeAST::codegen()
{
std::vector<llvm::Type *> doubles(args_.size(),
llvm::Type::getDoubleTy(*TheContext));
llvm::FunctionType *FT
= llvm::FunctionType::get(llvm::Type::getDoubleTy(*TheContext),
doubles,
false);
llvm::Function *F = llvm::Function::Create(FT,
llvm::Function::ExternalLinkage,
name_,
obelisk::TheModule.get());
unsigned idx = 0;
for (auto &arg : F->args())
{
arg.setName(args_[idx++]);
}
return F;
}

View File

@ -1,6 +1,8 @@
#ifndef OBELISK_AST_PROTOTYPE_AST_H
#define OBELISK_AST_PROTOTYPE_AST_H
#include <llvm/IR/Function.h>
#include <string>
#include <vector>
@ -28,6 +30,8 @@ namespace obelisk
{
return name_;
}
llvm::Function* codegen();
};
} //namespace obelisk

View File

@ -0,0 +1,13 @@
#include "ast/ast.h"
#include "ast/error.h"
#include "ast/variable_expression_ast.h"
llvm::Value *obelisk::VariableExpressionAST::codegen()
{
llvm::Value *V = NamedValues[name_];
if (!V)
{
return obelisk::LogErrorV("Unknown variable name");
}
return V;
}

View File

@ -19,6 +19,8 @@ namespace obelisk
name_(name)
{
}
llvm::Value *codegen() override;
};
} //namespace obelisk

View File

@ -1,18 +1,16 @@
#include "knowledge_base.h"
#include "models/action.h"
#include "models/entity.h"
#include "models/error.h"
#include "models/fact.h"
#include "models/rule.h"
#include "models/suggest_action.h"
#include "models/verb.h"
#include <cstring>
#include <filesystem>
#include <iostream>
obelisk::KnowledgeBase::KnowledgeBase(const char* filename)
{
KnowledgeBase(filename, DEFAULT_FLAGS);
}
#include <string>
obelisk::KnowledgeBase::KnowledgeBase(const char* filename, int flags)
{
@ -28,6 +26,8 @@ obelisk::KnowledgeBase::KnowledgeBase(const char* filename, int flags)
logSqliteError(result);
}
enableForeignKeys();
if (!dbExists)
{
createTable(obelisk::Action::createTable);
@ -47,16 +47,25 @@ obelisk::KnowledgeBase::~KnowledgeBase()
}
}
void obelisk::KnowledgeBase::createTable(std::function<const char*()> function)
/**
* @brief Enable foreign key functionality in the open database.
*
* This must always be done when the connection is opened or it will not
* enforce the foreign key constraints.
*/
void obelisk::KnowledgeBase::enableForeignKeys()
{
char* tmp;
auto result = sqlite3_exec(dbConnection_, function(), NULL, NULL, &tmp);
char* errmsg;
int result = sqlite3_exec(dbConnection_,
"PRAGMA foreign_keys = ON;",
NULL,
NULL,
&errmsg);
if (result != SQLITE_OK)
{
logSqliteError(result);
if (tmp)
if (errmsg)
{
std::string errmsg(tmp);
throw obelisk::KnowledgeBaseException(errmsg);
}
else
@ -66,7 +75,103 @@ void obelisk::KnowledgeBase::createTable(std::function<const char*()> function)
}
}
// TODO: log files?
void obelisk::KnowledgeBase::createTable(std::function<const char*()> function)
{
char* errmsg;
int result = sqlite3_exec(dbConnection_, function(), NULL, NULL, &errmsg);
if (result != SQLITE_OK)
{
logSqliteError(result);
if (errmsg)
{
throw obelisk::KnowledgeBaseException(errmsg);
}
else
{
throw obelisk::KnowledgeBaseException();
}
}
}
void obelisk::KnowledgeBase::addEntities(std::vector<obelisk::Entity>& entities)
{
for (auto& entity : entities)
{
try
{
entity.insertEntity(dbConnection_);
}
catch (obelisk::DatabaseException::ConstraintException& exception)
{
// ignore unique constraint error
if (std::strcmp(exception.what(),
"UNIQUE constraint failed: entity.name")
!= 0)
{
throw;
}
}
}
}
void obelisk::KnowledgeBase::addVerbs(std::vector<obelisk::Verb>& verbs)
{
for (auto& verb : verbs)
{
try
{
verb.insertVerb(dbConnection_);
}
catch (obelisk::DatabaseException::ConstraintException& exception)
{
// ignore unique constraint error
if (std::strcmp(exception.what(),
"UNIQUE constraint failed: verb.name")
!= 0)
{
throw;
}
}
}
}
void obelisk::KnowledgeBase::addFacts(std::vector<obelisk::Fact>& facts)
{
for (auto& fact : facts)
{
try
{
fact.insertFact(dbConnection_);
}
catch (obelisk::DatabaseException::ConstraintException& exception)
{
// ignore unique constraint error
if (std::strcmp(exception.what(),
"UNIQUE constraint failed: fact.left_entity, fact.right_entity, fact.verb")
!= 0)
{
throw;
}
}
}
}
void obelisk::KnowledgeBase::getEntity(obelisk::Entity& entity)
{
entity.selectEntity(dbConnection_);
}
void obelisk::KnowledgeBase::getVerb(obelisk::Verb& verb)
{
verb.selectVerb(dbConnection_);
}
void obelisk::KnowledgeBase::getFact(obelisk::Fact& fact)
{
fact.selectFact(dbConnection_);
}
// TODO: log files? or just throw an error?
void obelisk::KnowledgeBase::logSqliteError(int result)
{
std::cout << sqlite3_errstr(result) << std::endl;

View File

@ -1,10 +1,15 @@
#ifndef OBELISK_KNOWLEDGE_BASE_H
#define OBELISK_KNOWLEDGE_BASE_H
#include "models/entity.h"
#include "models/fact.h"
#include "models/verb.h"
#include <sqlite3.h>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
namespace obelisk
@ -19,19 +24,27 @@ namespace obelisk
int flags_;
void logSqliteError(int result);
void enableForeignKeys();
void createTable(std::function<const char*()> function);
public:
KnowledgeBase(const char* filename);
KnowledgeBase(const char* filename, int flags);
KnowledgeBase(const char* filename) :
KnowledgeBase(filename,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)
{
}
~KnowledgeBase();
template<typename T, typename U>
int addFacts(std::string verb, T leftEntities, U rightEntities);
// TODO: add parameter for fact
template<typename T, typename U>
int addRules(std::string verb, T leftEntities, U rightEntities);
template<typename T, typename U> int addActions();
void addEntities(std::vector<obelisk::Entity>& entities);
void addVerbs(std::vector<obelisk::Verb>& verbs);
void addFacts(std::vector<obelisk::Fact>& facts);
void getEntity(obelisk::Entity& entity);
void getVerb(obelisk::Verb& verb);
void getFact(obelisk::Fact& fact);
void getDouble(double& result, float var1, float var2);
void getFloat(float& result1, float& result2, double var);

View File

@ -13,8 +13,16 @@ obelisk_sources += obelisk_ast_sources
subdir('models')
obelisk_sources += obelisk_model_sources
r = run_command('llvm-config', '--cppflags', check : true)
cpp_args = ' ' + r.stdout().replace('\n', ' ').replace('-I', '-isystem')
r = run_command('llvm-config', '--ldflags', '--system-libs', '--libs', 'core', check : true)
link_args = ' ' + r.stdout().replace('\n', ' ')
executable('obelisk',
obelisk_sources,
dependencies : [sqlite3],
cpp_args : cpp_args.split(),
link_args : link_args.split(),
install : true
)

View File

@ -11,7 +11,7 @@ const char* obelisk::Action::createTable()
)";
}
int obelisk::Action::getId()
int& obelisk::Action::getId()
{
return id_;
}
@ -21,7 +21,7 @@ void obelisk::Action::setId(int id)
id_ = id;
}
std::string obelisk::Action::getName()
std::string& obelisk::Action::getName()
{
return name_;
}

View File

@ -38,10 +38,10 @@ namespace obelisk
static const char* createTable();
int getId();
int& getId();
void setId(int id);
std::string getName();
std::string& getName();
void setName(std::string name);
};
} // namespace obelisk

View File

@ -1,4 +1,5 @@
#include "models/entity.h"
#include "models/error.h"
const char* obelisk::Entity::createTable()
{
@ -11,7 +12,142 @@ const char* obelisk::Entity::createTable()
)";
}
int obelisk::Entity::getId()
void obelisk::Entity::selectEntity(sqlite3* dbConnection)
{
if (dbConnection == nullptr)
{
throw obelisk::DatabaseException("database isn't open");
}
sqlite3_stmt* ppStmt = nullptr;
auto result = sqlite3_prepare_v2(dbConnection,
"SELECT id, name FROM entity WHERE name=?",
-1,
&ppStmt,
nullptr);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
result = sqlite3_bind_text(ppStmt, 1, getName().c_str(), -1, SQLITE_STATIC);
switch (result)
{
case SQLITE_OK :
break;
case SQLITE_TOOBIG :
throw obelisk::DatabaseException::SizeException();
break;
case SQLITE_RANGE :
throw obelisk::DatabaseException::RangeException();
break;
case SQLITE_NOMEM :
throw obelisk::DatabaseException::MemoryException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_step(ppStmt);
switch (result)
{
case SQLITE_DONE :
// no rows in the database
break;
case SQLITE_ROW :
setId(sqlite3_column_int(ppStmt, 0));
setName((char*) sqlite3_column_text(ppStmt, 1));
break;
case SQLITE_BUSY :
throw obelisk::DatabaseException::BusyException();
break;
case SQLITE_MISUSE :
throw obelisk::DatabaseException::MisuseException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_finalize(ppStmt);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
}
void obelisk::Entity::insertEntity(sqlite3* dbConnection)
{
if (dbConnection == nullptr)
{
throw obelisk::DatabaseException("database isn't open");
}
sqlite3_stmt* ppStmt = nullptr;
auto result = sqlite3_prepare_v2(dbConnection,
"INSERT INTO entity (name) VALUES (?)",
-1,
&ppStmt,
nullptr);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
result
= sqlite3_bind_text(ppStmt, 1, getName().c_str(), -1, SQLITE_TRANSIENT);
switch (result)
{
case SQLITE_OK :
break;
case SQLITE_TOOBIG :
throw obelisk::DatabaseException::SizeException();
break;
case SQLITE_RANGE :
throw obelisk::DatabaseException::RangeException();
break;
case SQLITE_NOMEM :
throw obelisk::DatabaseException::MemoryException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_step(ppStmt);
switch (result)
{
case SQLITE_DONE :
setId((int) sqlite3_last_insert_rowid(dbConnection));
sqlite3_set_last_insert_rowid(dbConnection, 0);
break;
case SQLITE_CONSTRAINT :
throw obelisk::DatabaseException::ConstraintException(
sqlite3_errmsg(dbConnection));
case SQLITE_BUSY :
throw obelisk::DatabaseException::BusyException();
break;
case SQLITE_MISUSE :
throw obelisk::DatabaseException::MisuseException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_finalize(ppStmt);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
}
int& obelisk::Entity::getId()
{
return id_;
}
@ -21,7 +157,7 @@ void obelisk::Entity::setId(int id)
id_ = id;
}
std::string obelisk::Entity::getName()
std::string& obelisk::Entity::getName()
{
return name_;
}

View File

@ -1,6 +1,8 @@
#ifndef OBELISK_MODELS_ENTITY_H
#define OBELISK_MODELS_ENTITY_H
#include <sqlite3.h>
#include <string>
namespace obelisk
@ -38,11 +40,14 @@ namespace obelisk
static const char* createTable();
int getId();
int& getId();
void setId(int id);
std::string getName();
std::string& getName();
void setName(std::string name);
void selectEntity(sqlite3* dbConnection);
void insertEntity(sqlite3* dbConnection);
};
} // namespace obelisk

146
src/models/error.h Normal file
View File

@ -0,0 +1,146 @@
#ifndef OBELISK_MODELS_ERROR_H
#define OBELISK_MODELS_ERROR_H
#include <exception>
#include <string>
namespace obelisk
{
class DatabaseException : public std::exception
{
private:
const std::string errorMessage_;
public:
DatabaseException() :
errorMessage_("an unknown error ocurred")
{
}
DatabaseException(const int errorCode) :
errorMessage_(
"database error " + std::to_string(errorCode) + " ocurred")
{
}
DatabaseException(const std::string& errorMessage) :
errorMessage_(errorMessage)
{
}
const char* what() const noexcept
{
return errorMessage_.c_str();
}
class SizeException : public std::exception
{
private:
const std::string errorMessage_;
public:
SizeException() :
errorMessage_("size of string or blob exceeds limits")
{
}
const char* what() const noexcept
{
return errorMessage_.c_str();
}
};
class RangeException : public std::exception
{
private:
const std::string errorMessage_;
public:
RangeException() :
errorMessage_("parameter index is out of range")
{
}
const char* what() const noexcept
{
return errorMessage_.c_str();
}
};
class MemoryException : public std::exception
{
private:
const std::string errorMessage_;
public:
MemoryException() :
errorMessage_("not enough memory for operation")
{
}
const char* what() const noexcept
{
return errorMessage_.c_str();
}
};
class BusyException : public std::exception
{
private:
const std::string errorMessage_;
public:
BusyException() :
errorMessage_(
"database was busy and operation not performed")
{
}
const char* what() const noexcept
{
return errorMessage_.c_str();
}
};
class MisuseException : public std::exception
{
private:
const std::string errorMessage_;
public:
MisuseException() :
errorMessage_("misuse of the database routine")
{
}
const char* what() const noexcept
{
return errorMessage_.c_str();
}
};
class ConstraintException : public std::exception
{
private:
const std::string errorMessage_;
public:
ConstraintException() :
errorMessage_("a constraint exception occurred")
{
}
ConstraintException(const std::string& errorMessage) :
errorMessage_(errorMessage)
{
}
const char* what() const noexcept
{
return errorMessage_.c_str();
}
};
};
} // namespace obelisk
#endif

View File

@ -1,3 +1,4 @@
#include "models/error.h"
#include "models/fact.h"
const char* obelisk::Fact::createTable()
@ -9,6 +10,7 @@ const char* obelisk::Fact::createTable()
"right_entity" INTEGER NOT NULL,
"verb" INTEGER NOT NULL,
PRIMARY KEY("id" AUTOINCREMENT),
UNIQUE("left_entity", "right_entity", "verb")
FOREIGN KEY("verb") REFERENCES "verb"("id") ON DELETE RESTRICT,
FOREIGN KEY("right_entity") REFERENCES "entity"("id") ON DELETE RESTRICT,
FOREIGN KEY("left_entity") REFERENCES "entity"("id") ON DELETE RESTRICT
@ -16,7 +18,217 @@ const char* obelisk::Fact::createTable()
)";
}
int obelisk::Fact::getId()
void obelisk::Fact::selectFact(sqlite3* dbConnection)
{
if (dbConnection == nullptr)
{
throw obelisk::DatabaseException("database isn't open");
}
sqlite3_stmt* ppStmt = nullptr;
auto result = sqlite3_prepare_v2(dbConnection,
"SELECT id, left_entity, right_entity, verb FROM fact WHERE (left_entity=? AND right_entity=? AND verb=?)",
-1,
&ppStmt,
nullptr);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
result = sqlite3_bind_int(ppStmt, 1, getLeftEntity().getId());
switch (result)
{
case SQLITE_OK :
break;
case SQLITE_TOOBIG :
throw obelisk::DatabaseException::SizeException();
break;
case SQLITE_RANGE :
throw obelisk::DatabaseException::RangeException();
break;
case SQLITE_NOMEM :
throw obelisk::DatabaseException::MemoryException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_bind_int(ppStmt, 2, getRightEntity().getId());
switch (result)
{
case SQLITE_OK :
break;
case SQLITE_TOOBIG :
throw obelisk::DatabaseException::SizeException();
break;
case SQLITE_RANGE :
throw obelisk::DatabaseException::RangeException();
break;
case SQLITE_NOMEM :
throw obelisk::DatabaseException::MemoryException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_bind_int(ppStmt, 3, getVerb().getId());
switch (result)
{
case SQLITE_OK :
break;
case SQLITE_TOOBIG :
throw obelisk::DatabaseException::SizeException();
break;
case SQLITE_RANGE :
throw obelisk::DatabaseException::RangeException();
break;
case SQLITE_NOMEM :
throw obelisk::DatabaseException::MemoryException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_step(ppStmt);
switch (result)
{
case SQLITE_DONE :
// no rows in the database
break;
case SQLITE_ROW :
setId(sqlite3_column_int(ppStmt, 0));
getLeftEntity().setId(sqlite3_column_int(ppStmt, 1));
getRightEntity().setId(sqlite3_column_int(ppStmt, 2));
getVerb().setId(sqlite3_column_int(ppStmt, 3));
break;
case SQLITE_BUSY :
throw obelisk::DatabaseException::BusyException();
break;
case SQLITE_MISUSE :
throw obelisk::DatabaseException::MisuseException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_finalize(ppStmt);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
}
void obelisk::Fact::insertFact(sqlite3* dbConnection)
{
if (dbConnection == nullptr)
{
throw obelisk::DatabaseException("database isn't open");
}
sqlite3_stmt* ppStmt = nullptr;
auto result = sqlite3_prepare_v2(dbConnection,
"INSERT INTO fact (left_entity, right_entity, verb) VALUES (?, ?, ?)",
-1,
&ppStmt,
nullptr);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
result = sqlite3_bind_int(ppStmt, 1, getLeftEntity().getId());
switch (result)
{
case SQLITE_OK :
break;
case SQLITE_TOOBIG :
throw obelisk::DatabaseException::SizeException();
break;
case SQLITE_RANGE :
throw obelisk::DatabaseException::RangeException();
break;
case SQLITE_NOMEM :
throw obelisk::DatabaseException::MemoryException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_bind_int(ppStmt, 2, getRightEntity().getId());
switch (result)
{
case SQLITE_OK :
break;
case SQLITE_TOOBIG :
throw obelisk::DatabaseException::SizeException();
break;
case SQLITE_RANGE :
throw obelisk::DatabaseException::RangeException();
break;
case SQLITE_NOMEM :
throw obelisk::DatabaseException::MemoryException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_bind_int(ppStmt, 3, getVerb().getId());
switch (result)
{
case SQLITE_OK :
break;
case SQLITE_TOOBIG :
throw obelisk::DatabaseException::SizeException();
break;
case SQLITE_RANGE :
throw obelisk::DatabaseException::RangeException();
break;
case SQLITE_NOMEM :
throw obelisk::DatabaseException::MemoryException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_step(ppStmt);
switch (result)
{
case SQLITE_DONE :
setId((int) sqlite3_last_insert_rowid(dbConnection));
sqlite3_set_last_insert_rowid(dbConnection, 0);
break;
case SQLITE_CONSTRAINT :
throw obelisk::DatabaseException::ConstraintException(
sqlite3_errmsg(dbConnection));
case SQLITE_BUSY :
throw obelisk::DatabaseException::BusyException();
break;
case SQLITE_MISUSE :
throw obelisk::DatabaseException::MisuseException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_finalize(ppStmt);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
}
int& obelisk::Fact::getId()
{
return id_;
}
@ -26,7 +238,7 @@ void obelisk::Fact::setId(int id)
id_ = id;
}
obelisk::Entity obelisk::Fact::getLeftEntity()
obelisk::Entity& obelisk::Fact::getLeftEntity()
{
return leftEntity_;
}
@ -36,7 +248,7 @@ void obelisk::Fact::setLeftEntity(obelisk::Entity leftEntity)
leftEntity_ = leftEntity;
}
obelisk::Entity obelisk::Fact::getRightEntity()
obelisk::Entity& obelisk::Fact::getRightEntity()
{
return rightEntity_;
}
@ -46,7 +258,7 @@ void obelisk::Fact::setRightEntity(obelisk::Entity rightEntity)
rightEntity_ = rightEntity;
}
obelisk::Verb obelisk::Fact::getVerb()
obelisk::Verb& obelisk::Fact::getVerb()
{
return verb_;
}

View File

@ -2,6 +2,7 @@
#define OBELISK_MODELS_FACT_H
#include "models/entity.h"
#include "models/fact.h"
#include "models/verb.h"
#include <string>
@ -56,17 +57,20 @@ namespace obelisk
static const char* createTable();
int getId();
int& getId();
void setId(int id);
obelisk::Entity getLeftEntity();
Entity& getLeftEntity();
void setLeftEntity(obelisk::Entity leftEntity);
obelisk::Entity getRightEntity();
Entity& getRightEntity();
void setRightEntity(obelisk::Entity leftEntity);
obelisk::Verb getVerb();
Verb& getVerb();
void setVerb(obelisk::Verb verb);
void selectFact(sqlite3* dbConnection);
void insertFact(sqlite3* dbConnection);
};
} // namespace obelisk

View File

@ -8,13 +8,14 @@ const char* obelisk::Rule::createTable()
"fact" INTEGER NOT NULL,
"reason" INTEGER NOT NULL CHECK("reason" != "fact"),
PRIMARY KEY("id" AUTOINCREMENT),
UNIQUE("fact", "reason"),
FOREIGN KEY("fact") REFERENCES "fact"("id") ON DELETE RESTRICT,
FOREIGN KEY("reason") REFERENCES "fact"("id") ON DELETE RESTRICT
);
)";
}
int obelisk::Rule::getId()
int& obelisk::Rule::getId()
{
return id_;
}
@ -24,7 +25,7 @@ void obelisk::Rule::setId(int id)
id_ = id;
}
obelisk::Fact obelisk::Rule::getFact()
obelisk::Fact& obelisk::Rule::getFact()
{
return fact_;
}
@ -34,7 +35,7 @@ void obelisk::Rule::setFact(obelisk::Fact fact)
fact_ = fact;
}
obelisk::Fact obelisk::Rule::getReason()
obelisk::Fact& obelisk::Rule::getReason()
{
return reason_;
}

View File

@ -45,13 +45,13 @@ namespace obelisk
static const char* createTable();
int getId();
int& getId();
void setId(int id);
obelisk::Fact getFact();
obelisk::Fact& getFact();
void setFact(obelisk::Fact fact);
obelisk::Fact getReason();
obelisk::Fact& getReason();
void setReason(obelisk::Fact reason);
};
} // namespace obelisk

View File

@ -9,6 +9,7 @@ const char* obelisk::SuggestAction::createTable()
"true_action" INTEGER NOT NULL,
"false_action" INTEGER NOT NULL,
PRIMARY KEY("id" AUTOINCREMENT),
UNIQUE("fact", "true_action", "false_action"),
FOREIGN KEY("fact") REFERENCES "fact"("id") ON DELETE RESTRICT,
FOREIGN KEY("true_action") REFERENCES "action"("id") ON DELETE RESTRICT,
FOREIGN KEY("false_action") REFERENCES "action"("id") ON DELETE RESTRICT
@ -16,7 +17,7 @@ const char* obelisk::SuggestAction::createTable()
)";
}
int obelisk::SuggestAction::getId()
int& obelisk::SuggestAction::getId()
{
return id_;
}
@ -26,7 +27,7 @@ void obelisk::SuggestAction::setId(int id)
id_ = id;
}
obelisk::Fact obelisk::SuggestAction::getFact()
obelisk::Fact& obelisk::SuggestAction::getFact()
{
return fact_;
}
@ -36,7 +37,7 @@ void obelisk::SuggestAction::setFact(obelisk::Fact fact)
fact_ = fact;
}
obelisk::Action obelisk::SuggestAction::getTrueAction()
obelisk::Action& obelisk::SuggestAction::getTrueAction()
{
return trueAction_;
}
@ -46,7 +47,7 @@ void obelisk::SuggestAction::setTrueAction(obelisk::Action trueAction)
trueAction_ = trueAction;
}
obelisk::Action obelisk::SuggestAction::getFalseAction()
obelisk::Action& obelisk::SuggestAction::getFalseAction()
{
return falseAction_;
}

View File

@ -56,16 +56,16 @@ namespace obelisk
static const char* createTable();
int getId();
int& getId();
void setId(int id);
obelisk::Fact getFact();
obelisk::Fact& getFact();
void setFact(obelisk::Fact fact);
obelisk::Action getTrueAction();
obelisk::Action& getTrueAction();
void setTrueAction(obelisk::Action trueAction);
obelisk::Action getFalseAction();
obelisk::Action& getFalseAction();
void setFalseAction(obelisk::Action falseAction);
};
} // namespace obelisk

View File

@ -1,5 +1,8 @@
#include "models/error.h"
#include "models/verb.h"
#include <iostream>
const char* obelisk::Verb::createTable()
{
return R"(
@ -11,7 +14,140 @@ const char* obelisk::Verb::createTable()
)";
}
int obelisk::Verb::getId()
void obelisk::Verb::selectVerb(sqlite3* dbConnection)
{
if (dbConnection == nullptr)
{
throw obelisk::DatabaseException("database isn't open");
}
sqlite3_stmt* ppStmt = nullptr;
auto result = sqlite3_prepare_v2(dbConnection,
"SELECT id, name FROM verb WHERE name=?",
-1,
&ppStmt,
nullptr);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
result = sqlite3_bind_text(ppStmt, 1, getName().c_str(), -1, SQLITE_STATIC);
switch (result)
{
case SQLITE_OK :
break;
case SQLITE_TOOBIG :
throw obelisk::DatabaseException::SizeException();
break;
case SQLITE_RANGE :
throw obelisk::DatabaseException::RangeException();
break;
case SQLITE_NOMEM :
throw obelisk::DatabaseException::MemoryException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_step(ppStmt);
switch (result)
{
case SQLITE_DONE :
// no rows in the database
break;
case SQLITE_ROW :
setId(sqlite3_column_int(ppStmt, 0));
setName((char*) sqlite3_column_text(ppStmt, 1));
break;
case SQLITE_BUSY :
throw obelisk::DatabaseException::BusyException();
break;
case SQLITE_MISUSE :
throw obelisk::DatabaseException::MisuseException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_finalize(ppStmt);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
}
void obelisk::Verb::insertVerb(sqlite3* dbConnection)
{
if (dbConnection == nullptr)
{
throw obelisk::DatabaseException("database isn't open");
}
sqlite3_stmt* ppStmt = nullptr;
auto result = sqlite3_prepare_v2(dbConnection,
"INSERT INTO verb (name) VALUES (?)",
-1,
&ppStmt,
nullptr);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
result
= sqlite3_bind_text(ppStmt, 1, getName().c_str(), -1, SQLITE_TRANSIENT);
switch (result)
{
case SQLITE_OK :
break;
case SQLITE_TOOBIG :
throw obelisk::DatabaseException::SizeException();
break;
case SQLITE_RANGE :
throw obelisk::DatabaseException::RangeException();
break;
case SQLITE_NOMEM :
throw obelisk::DatabaseException::MemoryException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_step(ppStmt);
switch (result)
{
case SQLITE_DONE :
setId((int) sqlite3_last_insert_rowid(dbConnection));
sqlite3_set_last_insert_rowid(dbConnection, 0);
break;
case SQLITE_CONSTRAINT :
throw obelisk::DatabaseException::ConstraintException(
sqlite3_errmsg(dbConnection));
case SQLITE_BUSY :
throw obelisk::DatabaseException::BusyException();
break;
case SQLITE_MISUSE :
throw obelisk::DatabaseException::MisuseException();
break;
default :
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
break;
}
result = sqlite3_finalize(ppStmt);
if (result != SQLITE_OK)
{
throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection));
}
}
int& obelisk::Verb::getId()
{
return id_;
}
@ -21,7 +157,7 @@ void obelisk::Verb::setId(int id)
id_ = id;
}
std::string obelisk::Verb::getName()
std::string& obelisk::Verb::getName()
{
return name_;
}

View File

@ -1,6 +1,8 @@
#ifndef OBELISK_MODELS_VERB_H
#define OBELISK_MODELS_VERB_H
#include <sqlite3.h>
#include <string>
namespace obelisk
@ -38,11 +40,14 @@ namespace obelisk
static const char* createTable();
int getId();
int& getId();
void setId(int id);
std::string getName();
std::string& getName();
void setName(std::string name);
void selectVerb(sqlite3* dbConnection);
void insertVerb(sqlite3* dbConnection);
};
} // namespace obelisk

View File

@ -8,9 +8,21 @@
#include <limits>
#include <memory>
static void mainLoop()
static int mainLoop()
{
auto parser = std::unique_ptr<obelisk::Parser> {new obelisk::Parser()};
std::unique_ptr<obelisk::KnowledgeBase> kb;
try
{
kb = std::unique_ptr<obelisk::KnowledgeBase> {
new obelisk::KnowledgeBase("cromer.kb")};
}
catch (obelisk::KnowledgeBaseException& exception)
{
std::cout << exception.what() << std::endl;
return EXIT_FAILURE;
}
// Prime the first token.
fprintf(stderr, "ready> ");
@ -22,7 +34,7 @@ static void mainLoop()
switch (parser->getCurrentToken())
{
case obelisk::Lexer::kTokenEof :
return;
return EXIT_SUCCESS;
case ';' : // ignore top-level semicolons.
std::cout << "Identifier: "
<< parser->getLexer()->getIdentifier() << std::endl;
@ -31,19 +43,21 @@ static void mainLoop()
parser->getNextToken();
break;
case obelisk::Lexer::kTokenFact :
// parser->handleFactFunction();
parser->handleFact(kb);
break;
case obelisk::Lexer::kTokenRule :
// parser->handleRuleFunction();
// parser->handleRule();
break;
case obelisk::Lexer::kTokenAction :
// parser->handleActionFunction();
// parser->handleAction();
break;
default :
parser->getNextToken();
break;
}
}
return EXIT_SUCCESS;
}
int main(int argc, char** argv)
@ -79,28 +93,5 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}*/
try
{
auto kb = std::unique_ptr<obelisk::KnowledgeBase> {
new obelisk::KnowledgeBase("cromer.kb")};
/*std::vector<std::string> leftObjects;
std::vector<std::string> rightObjects;
leftObjects.push_back("chris");
leftObjects.push_back("martin");
rightObjects.push_back("happy");
rightObjects.push_back("smart");
kb->addFacts("is", leftObjects, rightObjects);*/
}
catch (obelisk::KnowledgeBaseException& exception)
{
std::cout << exception.what() << std::endl;
return EXIT_FAILURE;
}
mainLoop();
return EXIT_SUCCESS;
return mainLoop();
}

View File

@ -1 +1 @@
static void mainLoop();
static int mainLoop();

View File

@ -1,10 +1,14 @@
#include "ast/call_expression_ast.h"
#include "ast/number_expression_ast.h"
#include "ast/variable_expression_ast.h"
#include "models/entity.h"
#include "models/fact.h"
#include "models/verb.h"
#include "parser.h"
#include <memory>
#include <stack>
#include <string>
#include <vector>
obelisk::Parser::Parser()
@ -211,64 +215,27 @@ std::unique_ptr<obelisk::PrototypeAST> obelisk::Parser::parseExtern()
return parsePrototype();
}
//action("martin" is "dangerous" then "avoid" or "ignore");
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseAction()
{
//action(is "dangerous" then "avoid" or "ignore");
getNextToken();
if (getCurrentToken() != '(')
{
// TODO: throw an error
}
}
//rule("chris" and "martin" is "happy" if "chris" plays "playstation");
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseRule()
{
//rule("player" can "die" if "enemy1" is "dangerous");
getNextToken();
if (getCurrentToken() != '(')
{
// TODO: throw an error
}
while (true) //left side of Rule
{
getNextToken();
if (getCurrentToken() != '"')
{
//TODO: throw an error
}
/*if (getCurrentToken() == ')') // TODO: break if not string and not "and"
{
// TODO: save the verb
break;
}*/
}
while (true) //right side of Ruke
{
getNextToken();
if (getCurrentToken() != '"')
{
//TODO: throw an error
}
if (getCurrentToken() == ')')
{
// TODO: save the verb
break;
}
}
}
// fact("chris cromer" and "martin" and "Isabella" can "program" and "speak english");
// fact("" and "martin")
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseFact()
void obelisk::Parser::parseFact(std::vector<obelisk::Fact>& facts)
{
std::stack<char> syntax;
getNextToken();
if (getCurrentToken() != '(')
{
// TODO: throw an error
throw obelisk::ParserException(
"expected '(' but got '" + std::to_string(getCurrentToken()) + "'");
}
syntax.push('(');
@ -326,14 +293,29 @@ std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseFact()
{
if (getCurrentToken() == ')')
{
// TODO: throw an error if verb is empty
// TODO: throw an error if rightEntities has 0 elements
// closing parenthesis found, make sure we have everything needed
if (verb == "")
{
throw obelisk::ParserException("verb is empty");
}
if (leftEntities.size() == 0)
{
throw obelisk::ParserException(
"missing left side entities");
}
if (rightEntities.size() == 0)
{
throw obelisk::ParserException(
"missing right side entities");
}
break;
}
if (getCurrentToken() == '"')
{
// TODO: throw and error because there is an unexpected double quote.
throw obelisk::ParserException("unexpected '\"'");
break;
}
@ -352,22 +334,97 @@ std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseFact()
}
}
return nullptr;
for (auto& leftEntity : leftEntities)
{
for (auto& rightEntity : rightEntities)
{
facts.push_back(obelisk::Fact(obelisk::Entity(leftEntity),
obelisk::Entity(rightEntity),
obelisk::Verb(verb)));
}
}
}
void obelisk::Parser::handleAction()
void obelisk::Parser::handleAction(std::unique_ptr<obelisk::KnowledgeBase>& kb)
{
}
void obelisk::Parser::handleRule()
void obelisk::Parser::handleRule(std::unique_ptr<obelisk::KnowledgeBase>& kb)
{
}
void obelisk::Parser::handleFact()
void obelisk::Parser::handleFact(std::unique_ptr<obelisk::KnowledgeBase>& kb)
{
parseFact();
std::vector<obelisk::Fact> facts;
parseFact(facts);
int verbId = 0;
for (auto& fact : facts)
{
// TODO: doesn't work after first insert
std::vector<obelisk::Entity> entities {fact.getLeftEntity()};
kb->addEntities(entities);
fact.setLeftEntity(entities.front());
// the id was not inserted, so check if it exists in the database
if (fact.getLeftEntity().getId() == 0)
{
obelisk::Entity entity = fact.getLeftEntity();
kb->getEntity(entity);
if (entity.getId() == 0)
{
// TODO: throw an error here, it was not inserted, and doesn't exist in the database
}
else
{
fact.setLeftEntity(entity);
}
}
entities = {fact.getRightEntity()};
kb->addEntities(entities);
fact.setRightEntity(entities.front());
if (fact.getRightEntity().getId() == 0)
{
obelisk::Entity entity = fact.getRightEntity();
kb->getEntity(entity);
if (entity.getId() == 0)
{
// TODO: throw an error here, it was not inserted, and doesn't exist in the database
}
else
{
fact.setRightEntity(entity);
}
}
if (verbId == 0)
{
std::vector<obelisk::Verb> verbs = {fact.getVerb()};
kb->addVerbs(verbs);
if (verbs.front().getId() != 0)
{
// The verb was inserted
fact.setVerb(verbs.front());
verbId = fact.getVerb().getId();
}
else
{
// The verb is already already in the knowledge base
// TODO: SELECT the verb and save it into verbId
}
}
else
{
fact.getVerb().setId(verbId);
}
// INSERT INTO fact
std::vector<obelisk::Fact> facts {fact};
kb->addFacts(facts);
fact = facts.front();
}
}
void obelisk::Parser::insertFact()
{
}
// fact("chris cromer" and "martin" and "Isabella" can "program" and "speak english");

View File

@ -4,7 +4,9 @@
#include "ast/expression_ast.h"
#include "ast/function_ast.h"
#include "ast/prototype_ast.h"
#include "knowledge_base.h"
#include "lexer.h"
#include "models/fact.h"
#include <memory>
@ -34,7 +36,7 @@ namespace obelisk
std::unique_ptr<obelisk::PrototypeAST> parseExtern();
std::unique_ptr<obelisk::ExpressionAST> parseAction();
std::unique_ptr<obelisk::ExpressionAST> parseRule();
std::unique_ptr<obelisk::ExpressionAST> parseFact();
void parseFact(std::vector<obelisk::Fact>& facts);
public:
Parser();
@ -48,9 +50,31 @@ namespace obelisk
void handleDefinition();
void handleExtern();
void handleTopLevelExpression();
void handleAction();
void handleRule();
void handleFact();
void handleAction(std::unique_ptr<obelisk::KnowledgeBase>& kb);
void handleRule(std::unique_ptr<obelisk::KnowledgeBase>& kb);
void handleFact(std::unique_ptr<obelisk::KnowledgeBase>& kb);
};
class ParserException : public std::exception
{
private:
const std::string errorMessage_;
public:
ParserException() :
errorMessage_("an unknown error ocurred")
{
}
ParserException(const std::string& errorMessage) :
errorMessage_(errorMessage)
{
}
const char* what() const noexcept
{
return errorMessage_.c_str();
}
};
} // namespace obelisk