2021-04-17 19:36:25 +01:00
|
|
|
/*
|
2021-10-12 20:51:03 +01:00
|
|
|
* Serene Programming Language
|
2021-04-11 00:02:56 +01:00
|
|
|
*
|
2022-01-27 11:44:44 +00:00
|
|
|
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
2021-04-11 00:02:56 +01:00
|
|
|
*
|
2021-10-12 20:51:03 +01:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, version 2.
|
2021-04-11 00:02:56 +01:00
|
|
|
*
|
2021-10-12 20:51:03 +01:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2021-04-11 00:02:56 +01:00
|
|
|
*
|
2021-10-12 20:51:03 +01:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2021-04-11 00:02:56 +01:00
|
|
|
*/
|
|
|
|
|
2021-04-17 19:36:25 +01:00
|
|
|
#include "serene/exprs/def.h"
|
2021-06-13 22:58:46 +01:00
|
|
|
|
2021-04-22 10:20:15 +01:00
|
|
|
#include "serene/errors/error.h"
|
2021-08-07 21:09:18 +01:00
|
|
|
#include "serene/exprs/expression.h"
|
2021-06-01 20:47:46 +01:00
|
|
|
#include "serene/exprs/fn.h"
|
2021-04-11 00:02:56 +01:00
|
|
|
#include "serene/exprs/list.h"
|
2021-04-22 10:20:15 +01:00
|
|
|
#include "serene/exprs/symbol.h"
|
2021-06-01 20:47:46 +01:00
|
|
|
#include "serene/exprs/traits.h"
|
2022-01-22 11:31:04 +00:00
|
|
|
#include "serene/slir/dialect.h"
|
|
|
|
#include "serene/slir/utils.h"
|
2021-06-13 22:58:46 +01:00
|
|
|
|
2021-06-23 20:34:57 +01:00
|
|
|
#include <llvm/Support/Casting.h>
|
|
|
|
#include <llvm/Support/ErrorHandling.h>
|
|
|
|
#include <llvm/Support/FormatVariadic.h>
|
2021-04-11 00:02:56 +01:00
|
|
|
|
|
|
|
namespace serene {
|
|
|
|
namespace exprs {
|
|
|
|
|
2021-04-17 19:36:25 +01:00
|
|
|
ExprType Def::getType() const { return ExprType::Def; };
|
2021-04-11 00:02:56 +01:00
|
|
|
|
2021-04-17 19:36:25 +01:00
|
|
|
std::string Def::toString() const {
|
2021-04-22 00:49:11 +01:00
|
|
|
return llvm::formatv("<Def {0} -> {1}>", this->binding,
|
|
|
|
this->value->toString());
|
2021-04-17 19:36:25 +01:00
|
|
|
}
|
2021-04-11 00:02:56 +01:00
|
|
|
|
2021-11-17 17:37:45 +00:00
|
|
|
MaybeNode Def::analyze(semantics::AnalysisState &state) {
|
|
|
|
UNUSED(state);
|
|
|
|
|
2021-09-27 13:05:15 +01:00
|
|
|
return EmptyNode;
|
|
|
|
};
|
2021-04-11 00:02:56 +01:00
|
|
|
|
2021-04-17 19:36:25 +01:00
|
|
|
bool Def::classof(const Expression *e) {
|
|
|
|
return e->getType() == ExprType::Def;
|
2021-04-11 00:02:56 +01:00
|
|
|
};
|
|
|
|
|
2021-11-17 17:37:45 +00:00
|
|
|
MaybeNode Def::make(semantics::AnalysisState &state, List *list) {
|
2021-04-22 10:20:15 +01:00
|
|
|
// TODO: Add support for docstring as the 3rd argument (4th element)
|
|
|
|
if (list->count() != 3) {
|
2021-04-23 16:48:14 +01:00
|
|
|
std::string msg = llvm::formatv("Expected 3 got {0}", list->count());
|
2021-05-06 19:17:57 +01:00
|
|
|
return makeErrorful<Node>(list->elements[0]->location,
|
2021-10-24 12:34:20 +01:00
|
|
|
errors::DefWrongNumberOfArgs, msg);
|
2021-04-22 10:20:15 +01:00
|
|
|
}
|
|
|
|
|
2021-04-24 19:10:18 +01:00
|
|
|
// Make sure that the list starts with a `def`
|
2021-04-24 18:04:04 +01:00
|
|
|
Symbol *defSym = llvm::dyn_cast<Symbol>(list->elements[0].get());
|
2021-08-07 21:09:18 +01:00
|
|
|
|
2021-04-24 18:04:04 +01:00
|
|
|
assert((defSym && defSym->name == "def") &&
|
|
|
|
"The first element of the list should be a 'def'.");
|
|
|
|
|
2021-04-24 19:10:18 +01:00
|
|
|
// Make sure that the first argument is a Symbol
|
2021-04-22 10:20:15 +01:00
|
|
|
Symbol *binding = llvm::dyn_cast<Symbol>(list->elements[1].get());
|
2021-10-17 14:33:16 +01:00
|
|
|
if (binding == nullptr) {
|
2021-05-06 19:17:57 +01:00
|
|
|
return makeErrorful<Node>(list->elements[1]->location,
|
2021-10-24 12:34:20 +01:00
|
|
|
errors::DefExpectSymbol, "");
|
2021-04-22 10:20:15 +01:00
|
|
|
}
|
|
|
|
|
2021-04-24 19:10:18 +01:00
|
|
|
// Analyze the value
|
2021-11-17 17:37:45 +00:00
|
|
|
MaybeNode value = list->elements[2]->analyze(state);
|
2021-04-25 23:02:52 +01:00
|
|
|
Node analyzedValue;
|
2021-04-24 19:10:18 +01:00
|
|
|
|
2021-08-07 21:09:18 +01:00
|
|
|
// TODO: To refactor this logic into a generic function
|
2021-04-24 19:10:18 +01:00
|
|
|
if (value) {
|
|
|
|
// Success value
|
|
|
|
auto &valueNode = value.getValue();
|
|
|
|
|
|
|
|
if (valueNode) {
|
|
|
|
// A rewrite is necessary
|
|
|
|
analyzedValue = valueNode;
|
|
|
|
} else {
|
|
|
|
// no rewrite
|
|
|
|
analyzedValue = list->elements[2];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Error value
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2021-06-01 20:47:46 +01:00
|
|
|
if (analyzedValue->getType() == ExprType::Fn) {
|
|
|
|
Fn *tmp = llvm::dyn_cast<Fn>(analyzedValue.get());
|
2021-10-17 14:33:16 +01:00
|
|
|
if (tmp == nullptr) {
|
2021-06-01 20:47:46 +01:00
|
|
|
llvm_unreachable("inconsistent getType for function");
|
|
|
|
}
|
2021-08-07 21:09:18 +01:00
|
|
|
|
2021-06-01 20:47:46 +01:00
|
|
|
tmp->setName(binding->name);
|
|
|
|
}
|
2021-08-07 21:09:18 +01:00
|
|
|
|
2021-11-17 17:37:45 +00:00
|
|
|
auto result = state.ns.define(binding->name, analyzedValue);
|
2021-04-29 23:39:58 +01:00
|
|
|
|
2021-05-08 19:00:24 +01:00
|
|
|
if (result.succeeded()) {
|
|
|
|
return makeSuccessfulNode<Def>(list->location, binding->name,
|
|
|
|
analyzedValue);
|
|
|
|
}
|
2021-10-17 14:33:16 +01:00
|
|
|
llvm_unreachable("Inserting a value in the semantic env failed!");
|
2021-04-22 00:49:11 +01:00
|
|
|
};
|
2021-08-07 17:41:19 +01:00
|
|
|
|
2021-08-15 12:06:56 +01:00
|
|
|
void Def::generateIR(serene::Namespace &ns, mlir::ModuleOp &m) {
|
2021-06-23 20:34:57 +01:00
|
|
|
|
|
|
|
if (value->getType() == ExprType::Fn) {
|
2021-08-15 12:06:56 +01:00
|
|
|
value->generateIR(ns, m);
|
2021-06-23 20:34:57 +01:00
|
|
|
return;
|
|
|
|
}
|
2022-01-22 11:31:04 +00:00
|
|
|
|
|
|
|
// auto loc = slir::toMLIRLocation(ns, location.start);
|
|
|
|
// auto &mctx = ns.getContext().mlirContext;
|
|
|
|
|
|
|
|
// mlir::OpBuilder builder(&mctx);
|
|
|
|
|
|
|
|
// auto sym = slir::SymbolType::get(&mctx, ns.name, binding);
|
|
|
|
|
|
|
|
// TODO: we need to change the generate method of expressions
|
|
|
|
// to return mlir::Value or any wrapper of that which would
|
|
|
|
// be the ssa form of the result of the expression.
|
|
|
|
// and then use it to define the def op here.
|
|
|
|
// auto def = builder.create<slir::DefOp>(sym, binding, value);
|
2021-08-15 12:06:56 +01:00
|
|
|
m.emitError("Def: not implemented!");
|
2021-06-23 20:34:57 +01:00
|
|
|
};
|
2021-04-11 00:02:56 +01:00
|
|
|
} // namespace exprs
|
|
|
|
} // namespace serene
|