Finalize migration to new expression interface
This commit is contained in:
parent
e4b0823e49
commit
555e770c01
|
@ -60,7 +60,13 @@ int main(int argc, char *argv[]) {
|
||||||
case Action::DumpIR: {
|
case Action::DumpIR: {
|
||||||
reader::FileReader *r = new reader::FileReader(inputFile);
|
reader::FileReader *r = new reader::FileReader(inputFile);
|
||||||
|
|
||||||
serene::sir::dumpSIR(*r->read());
|
auto ast = r->read();
|
||||||
|
|
||||||
|
if (!ast) {
|
||||||
|
throw ast.takeError();
|
||||||
|
}
|
||||||
|
|
||||||
|
serene::sir::dumpSIR(*ast);
|
||||||
delete r;
|
delete r;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* -*- C++ -*-
|
||||||
|
* Serene programming language.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERENE_ERRORS_H
|
||||||
|
#define SERENE_ERRORS_H
|
||||||
|
|
||||||
|
#include "serene/errors/errc.h"
|
||||||
|
#include "serene/errors/error.h"
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* -*- C++ -*-
|
||||||
|
* Serene programming language.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERENE_ERRORS_ERRC_H
|
||||||
|
#define SERENE_ERRORS_ERRC_H
|
||||||
|
|
||||||
|
#include "llvm/Support/Errc.h"
|
||||||
|
|
||||||
|
namespace serene {
|
||||||
|
|
||||||
|
/// A collection of common error codes in Serene
|
||||||
|
enum class errc {
|
||||||
|
argument_list_too_long = int(std::errc::argument_list_too_long),
|
||||||
|
argument_out_of_domain = int(std::errc::argument_out_of_domain),
|
||||||
|
bad_address = int(std::errc::bad_address),
|
||||||
|
bad_file_descriptor = int(std::errc::bad_file_descriptor),
|
||||||
|
broken_pipe = int(std::errc::broken_pipe),
|
||||||
|
device_or_resource_busy = int(std::errc::device_or_resource_busy),
|
||||||
|
directory_not_empty = int(std::errc::directory_not_empty),
|
||||||
|
executable_format_error = int(std::errc::executable_format_error),
|
||||||
|
file_exists = int(std::errc::file_exists),
|
||||||
|
file_too_large = int(std::errc::file_too_large),
|
||||||
|
filename_too_long = int(std::errc::filename_too_long),
|
||||||
|
function_not_supported = int(std::errc::function_not_supported),
|
||||||
|
illegal_byte_sequence = int(std::errc::illegal_byte_sequence),
|
||||||
|
inappropriate_io_control_operation =
|
||||||
|
int(std::errc::inappropriate_io_control_operation),
|
||||||
|
interrupted = int(std::errc::interrupted),
|
||||||
|
invalid_argument = int(std::errc::invalid_argument),
|
||||||
|
invalid_seek = int(std::errc::invalid_seek),
|
||||||
|
io_error = int(std::errc::io_error),
|
||||||
|
is_a_directory = int(std::errc::is_a_directory),
|
||||||
|
no_child_process = int(std::errc::no_child_process),
|
||||||
|
no_lock_available = int(std::errc::no_lock_available),
|
||||||
|
no_space_on_device = int(std::errc::no_space_on_device),
|
||||||
|
no_such_device_or_address = int(std::errc::no_such_device_or_address),
|
||||||
|
no_such_device = int(std::errc::no_such_device),
|
||||||
|
no_such_file_or_directory = int(std::errc::no_such_file_or_directory),
|
||||||
|
no_such_process = int(std::errc::no_such_process),
|
||||||
|
not_a_directory = int(std::errc::not_a_directory),
|
||||||
|
not_enough_memory = int(std::errc::not_enough_memory),
|
||||||
|
not_supported = int(std::errc::not_supported),
|
||||||
|
operation_not_permitted = int(std::errc::operation_not_permitted),
|
||||||
|
permission_denied = int(std::errc::permission_denied),
|
||||||
|
read_only_file_system = int(std::errc::read_only_file_system),
|
||||||
|
resource_deadlock_would_occur = int(std::errc::resource_deadlock_would_occur),
|
||||||
|
resource_unavailable_try_again =
|
||||||
|
int(std::errc::resource_unavailable_try_again),
|
||||||
|
result_out_of_range = int(std::errc::result_out_of_range),
|
||||||
|
too_many_files_open_in_system = int(std::errc::too_many_files_open_in_system),
|
||||||
|
too_many_files_open = int(std::errc::too_many_files_open),
|
||||||
|
too_many_links = int(std::errc::too_many_links)
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The **official way** to create `std::error_code` in context of Serene.
|
||||||
|
inline std::error_code make_error_code(errc E) {
|
||||||
|
return std::error_code(static_cast<int>(E), std::generic_category());
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace serene
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,30 @@
|
||||||
|
/* -*- C++ -*-
|
||||||
|
* Serene programming language.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERENE_ERRORS_ERROR_H
|
||||||
|
#define SERENE_ERRORS_ERROR_H
|
||||||
|
|
||||||
|
#include "llvm/Support/Error.h"
|
||||||
|
|
||||||
|
#endif
|
|
@ -30,136 +30,67 @@
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
|
|
||||||
/// Contains all the builtin expressions including those which do not appear in
|
/// Contains all the builtin AST expressions including those which do not appear
|
||||||
/// the syntax directly. Like function definitions.
|
/// in the syntax directly. Like function definitions.
|
||||||
namespace exprs {
|
namespace exprs {
|
||||||
|
|
||||||
/// This enum represent the expression type and **not** the value type.
|
/// This enum represent the expression type and **not** the value type.
|
||||||
enum class ExprType {
|
enum class ExprType {
|
||||||
Symbol,
|
Symbol,
|
||||||
List,
|
List,
|
||||||
|
Number,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The polymorphic type that works as the entry point to the exprs system.
|
/// The base class of the expressions which provides the common interface for
|
||||||
/// Each expression has to define the interface of the `ExpressionConcept`
|
/// the expressions to implement.
|
||||||
/// class as generic functions. **REMEMBER TO NOT INHERIT FROM THESE CLASSES**
|
|
||||||
class Expression {
|
class Expression {
|
||||||
public:
|
public:
|
||||||
|
/// The location range provide information regarding to where in the input
|
||||||
|
/// string the current expression is used.
|
||||||
reader::LocationRange location;
|
reader::LocationRange location;
|
||||||
|
|
||||||
Expression(const reader::LocationRange &loc) : location(loc){};
|
Expression(const reader::LocationRange &loc) : location(loc){};
|
||||||
virtual ~Expression() = default;
|
virtual ~Expression() = default;
|
||||||
|
|
||||||
|
/// Returns the type of the expression. We need this funciton to perform
|
||||||
|
/// dynamic casting of expression object to implementations such as lisp or
|
||||||
|
/// symbol.
|
||||||
virtual ExprType getType() const = 0;
|
virtual ExprType getType() const = 0;
|
||||||
|
|
||||||
|
/// The AST representation of an expression
|
||||||
virtual std::string toString() const = 0;
|
virtual std::string toString() const = 0;
|
||||||
};
|
};
|
||||||
|
using node = std::shared_ptr<Expression>;
|
||||||
|
using ast = llvm::SmallVector<node, 0>;
|
||||||
|
|
||||||
/// Create a new Expression of type `T` and forwards any given parameter
|
/// Create a new `node` of type `T` and forwards any given parameter
|
||||||
/// to the constructor of type `T`. This is the **official way** to create
|
/// to the constructor of type `T`. This is the **official way** to create
|
||||||
/// a new `Expression`. Here is an example:
|
/// a new `Expression`. Here is an example:
|
||||||
/// \code
|
/// \code
|
||||||
/// auto list = Expression::make<List>();
|
/// auto list = make<List>();
|
||||||
/// \endcode
|
/// \endcode
|
||||||
///
|
///
|
||||||
/// \param loc A `serene::reader::LocationRange` instance to point to exact
|
|
||||||
/// location of the expression in the input string.
|
|
||||||
/// \param[args] Any argument with any type passed to this function will be
|
/// \param[args] Any argument with any type passed to this function will be
|
||||||
/// passed to the constructor of type T.
|
/// passed to the constructor of type T.
|
||||||
/// \return A new expression containing a value of type T and act as tyep T.
|
/// \return A shared pointer to an Expression
|
||||||
// template <typename T, typename... Args> std::shared_ptr<T> make(Args
|
template <typename T, typename... Args> node make(Args &&...args) {
|
||||||
// &&...args);
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
std::shared_ptr<T> make(Args &&...args) {
|
|
||||||
return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
|
return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
|
||||||
};
|
};
|
||||||
|
|
||||||
using node = std::shared_ptr<Expression>;
|
/// Create a new `node` of type `T` and forwards any given parameter
|
||||||
using ast = llvm::SmallVector<node, 0>;
|
/// to the constructor of type `T`. This is the **official way** to create
|
||||||
// /// Creates a new expression by moving the given object of the type T into
|
/// a new `Expression`. Here is an example:
|
||||||
// /// a new internal container.
|
/// \code
|
||||||
// ///
|
/// auto list = make<List>();
|
||||||
// /// \param e and expression of type T
|
/// \endcode
|
||||||
// template <typename T> Expression(T e) : self(new Impl<T>(std::move(e))){};
|
///
|
||||||
|
/// \param[args] Any argument with any type passed to this function will be
|
||||||
// /// The copy constructor which actually just move the other expression into
|
/// passed to the constructor of type T.
|
||||||
// /// a new implementation container.
|
/// \return A shared pointer to a value of type T.
|
||||||
// ///
|
template <typename T, typename... Args>
|
||||||
// /// \param e is the other expression to copy from
|
std::shared_ptr<T> makeAndCast(Args &&...args) {
|
||||||
// Expression(const Expression &e) : self(e.self->copy_()){}; // Copy ctor
|
return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
|
||||||
// Expression(Expression &&e) noexcept = default; // Move ctor
|
};
|
||||||
|
|
||||||
// Expression &operator=(const Expression &e);
|
|
||||||
// Expression &operator=(Expression &&e) noexcept = default;
|
|
||||||
|
|
||||||
// /// Returns the type of the expression. More precisely, It returns the type
|
|
||||||
// /// of the expression that it contains.
|
|
||||||
// ///
|
|
||||||
// /// \return The type of expression.
|
|
||||||
// ExprType getType();
|
|
||||||
|
|
||||||
// /// Return the string representation of the expression in the context
|
|
||||||
// /// of the AST. Think of it as dump of the AST for each expression.
|
|
||||||
// ///
|
|
||||||
// /// \return the exoression in string format.
|
|
||||||
// std::string toString();
|
|
||||||
|
|
||||||
// /// Create a new Expression of type `T` and forwards any given parameter
|
|
||||||
// /// to the constructor of type `T`. This is the **official way** to create
|
|
||||||
// /// a new `Expression`. Here is an example:
|
|
||||||
// /// \code
|
|
||||||
// /// auto list = Expression::make<List>();
|
|
||||||
// /// \endcode
|
|
||||||
// ///
|
|
||||||
// /// \param loc A `serene::reader::LocationRange` instance to point to exact
|
|
||||||
// /// location of the expression in the input string.
|
|
||||||
// /// \param[args] Any argument with any type passed to this function will be
|
|
||||||
// /// passed to the constructor of type T.
|
|
||||||
// /// \return A new expression containing a value of type T and act as tyep T.
|
|
||||||
// template <typename T, typename... Args>
|
|
||||||
// static Expression make(Args &&...args) {
|
|
||||||
// return Expression(T(std::forward<Args>(args)...));
|
|
||||||
// };
|
|
||||||
|
|
||||||
// template <typename T> std::unique_ptr<T> *to();
|
|
||||||
// // template <typename T> static Expression make(reader::LocationRange &&loc)
|
|
||||||
// {
|
|
||||||
// // Expression e(T(std::forward<reader::LocationRange>(loc)));
|
|
||||||
// // return e;
|
|
||||||
// // };
|
|
||||||
|
|
||||||
// /// The generic interface which each type of expression has to implement
|
|
||||||
// /// in order to act like an `Expression`
|
|
||||||
// class ExpressionConcept {
|
|
||||||
// public:
|
|
||||||
// virtual ~ExpressionConcept() = default;
|
|
||||||
// virtual ExpressionConcept *copy_() const = 0;
|
|
||||||
|
|
||||||
// /// Return the type of the expression
|
|
||||||
// virtual ExprType getType() = 0;
|
|
||||||
|
|
||||||
// /// Return the string representation of the expression in the context
|
|
||||||
// /// of the AST. Think of it as dump of the AST for each expression
|
|
||||||
// virtual std::string toString() = 0;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// /// The generic implementation of `ExpressionConcept` which acts as the
|
|
||||||
// /// dispatcher on type.
|
|
||||||
// template <typename T> struct Impl : ExpressionConcept {
|
|
||||||
// Impl(T e) : expr(std::move(e)){};
|
|
||||||
|
|
||||||
// ExpressionConcept *copy_() const { return new Impl(*this); }
|
|
||||||
|
|
||||||
// /// In order to make llvm's RTTI to work we need this method.
|
|
||||||
// ExprType getType() const { return expr.getType(); }
|
|
||||||
|
|
||||||
// std::string toString() { return expr.toString(); }
|
|
||||||
|
|
||||||
// T expr;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// /// The internal container to keep the object implementing the
|
|
||||||
// /// `ExpressionConcept`. This might be a `List` for example or a `Symbol`.
|
|
||||||
// std::unique_ptr<ExpressionConcept> self;
|
|
||||||
|
|
||||||
} // namespace exprs
|
} // namespace exprs
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
|
@ -33,8 +33,12 @@ namespace serene {
|
||||||
|
|
||||||
namespace exprs {
|
namespace exprs {
|
||||||
|
|
||||||
|
/// This class represents a List in the AST level and not the List as the data
|
||||||
|
/// type.
|
||||||
class List : public Expression {
|
class List : public Expression {
|
||||||
public:
|
public:
|
||||||
|
// Internal elements of the lest (small vector of shared pointers to
|
||||||
|
// expressions)
|
||||||
ast elements;
|
ast elements;
|
||||||
|
|
||||||
List(const List &l); // Copy ctor
|
List(const List &l); // Copy ctor
|
||||||
|
@ -47,6 +51,8 @@ public:
|
||||||
ExprType getType() const;
|
ExprType getType() const;
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
|
void append(node);
|
||||||
|
|
||||||
static bool classof(const Expression *e);
|
static bool classof(const Expression *e);
|
||||||
|
|
||||||
~List() = default;
|
~List() = default;
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/* -*- C++ -*-
|
||||||
|
* Serene programming language.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXPRS_NUMBER_H
|
||||||
|
#define EXPRS_NUMBER_H
|
||||||
|
|
||||||
|
#include "serene/exprs/expression.h"
|
||||||
|
|
||||||
|
namespace serene {
|
||||||
|
|
||||||
|
namespace exprs {
|
||||||
|
|
||||||
|
/// This data structure represent the Lisp symbol. Just a symbol
|
||||||
|
/// in the context of the AST and nothing else.
|
||||||
|
struct Number : public Expression {
|
||||||
|
std::string value;
|
||||||
|
|
||||||
|
bool isNeg;
|
||||||
|
bool isFloat;
|
||||||
|
|
||||||
|
Number(reader::LocationRange &loc, const std::string &num, bool isNeg,
|
||||||
|
bool isFloat)
|
||||||
|
: Expression(loc), value(num), isNeg(isNeg), isFloat(isFloat){};
|
||||||
|
|
||||||
|
ExprType getType() const;
|
||||||
|
std::string toString() const;
|
||||||
|
|
||||||
|
int64_t toI64();
|
||||||
|
|
||||||
|
static bool classof(const Expression *e);
|
||||||
|
|
||||||
|
~Number() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace exprs
|
||||||
|
} // namespace serene
|
||||||
|
|
||||||
|
#endif
|
|
@ -33,6 +33,8 @@ namespace serene {
|
||||||
|
|
||||||
namespace exprs {
|
namespace exprs {
|
||||||
|
|
||||||
|
/// This data structure represent the Lisp symbol. Just a symbol
|
||||||
|
/// in the context of the AST and nothing else.
|
||||||
struct Symbol : public Expression {
|
struct Symbol : public Expression {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
|
|
|
@ -27,18 +27,15 @@
|
||||||
|
|
||||||
#include "mlir/IR/BuiltinOps.h"
|
#include "mlir/IR/BuiltinOps.h"
|
||||||
#include "mlir/IR/Value.h"
|
#include "mlir/IR/Value.h"
|
||||||
#include "serene/expr.hpp"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/logger.hpp"
|
#include "serene/logger.hpp"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include <llvm/IR/Module.h>
|
#include <llvm/IR/Module.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#if defined(ENABLE_LOG) || defined(ENABLE_NAMESPACE_LOG)
|
#define NAMESPACE_LOG(...) \
|
||||||
#define NAMESPACE_LOG(...) __LOG("NAMESPACE", __VA_ARGS__);
|
DEBUG_WITH_TYPE("NAMESPACE", llvm::dbgs() << __VA_ARGS__ << "\n");
|
||||||
#else
|
|
||||||
#define NAMESPACE_LOG(...) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using ScopeMap = llvm::DenseMap<llvm::StringRef, mlir::Value>;
|
using ScopeMap = llvm::DenseMap<llvm::StringRef, mlir::Value>;
|
||||||
using PairT = std::pair<llvm::StringRef, mlir::Value>;
|
using PairT = std::pair<llvm::StringRef, mlir::Value>;
|
||||||
|
@ -48,7 +45,7 @@ class AExpr;
|
||||||
|
|
||||||
class Namespace {
|
class Namespace {
|
||||||
private:
|
private:
|
||||||
ast_tree tree{};
|
exprs::ast tree{};
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
||||||
ScopeMap rootScope;
|
ScopeMap rootScope;
|
||||||
|
@ -59,8 +56,8 @@ public:
|
||||||
|
|
||||||
Namespace(llvm::StringRef ns_name, llvm::Optional<llvm::StringRef> filename);
|
Namespace(llvm::StringRef ns_name, llvm::Optional<llvm::StringRef> filename);
|
||||||
|
|
||||||
ast_tree &Tree();
|
exprs::ast &Tree();
|
||||||
mlir::LogicalResult setTree(ast_tree);
|
mlir::LogicalResult setTree(exprs::ast &);
|
||||||
// TODO: Fix it to return llvm::Optional<mlir::Value> instead
|
// TODO: Fix it to return llvm::Optional<mlir::Value> instead
|
||||||
llvm::Optional<mlir::Value> lookup(llvm::StringRef name);
|
llvm::Optional<mlir::Value> lookup(llvm::StringRef name);
|
||||||
mlir::LogicalResult insert_symbol(llvm::StringRef name, mlir::Value v);
|
mlir::LogicalResult insert_symbol(llvm::StringRef name, mlir::Value v);
|
|
@ -0,0 +1,64 @@
|
||||||
|
/* -*- C++ -*-
|
||||||
|
* Serene programming language.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERENE_READER_ERRORS_H
|
||||||
|
#define SERENE_READER_ERRORS_H
|
||||||
|
#include "serene/errors.h"
|
||||||
|
|
||||||
|
namespace serene {
|
||||||
|
namespace reader {
|
||||||
|
|
||||||
|
class ReadError : public std::exception {
|
||||||
|
private:
|
||||||
|
char *message;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReadError(char *msg) : message(msg){};
|
||||||
|
const char *what() const throw() { return message; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class MissingFileError : public llvm::ErrorInfo<MissingFileError> {
|
||||||
|
|
||||||
|
using llvm::ErrorInfo<MissingFileError>::log;
|
||||||
|
using llvm::ErrorInfo<MissingFileError>::convertToErrorCode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static char ID;
|
||||||
|
std::string path;
|
||||||
|
|
||||||
|
// TODO: Move this to an error namespace somewhere.
|
||||||
|
int file_is_missing = int();
|
||||||
|
|
||||||
|
void log(llvm::raw_ostream &os) const {
|
||||||
|
os << "File does not exist: " << path << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
MissingFileError(llvm::StringRef path) : path(path.str()){};
|
||||||
|
std::error_code convertToErrorCode() const {
|
||||||
|
return make_error_code(errc::no_such_file_or_directory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace reader
|
||||||
|
} // namespace serene
|
||||||
|
#endif
|
|
@ -29,15 +29,19 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <system_error>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "serene/expr.hpp"
|
#include "serene/errors.h"
|
||||||
#include "serene/list.hpp"
|
#include "serene/exprs/expression.h"
|
||||||
|
#include "serene/exprs/list.h"
|
||||||
|
#include "serene/exprs/symbol.h"
|
||||||
#include "serene/logger.hpp"
|
#include "serene/logger.hpp"
|
||||||
|
#include "serene/reader/errors.h"
|
||||||
#include "serene/reader/location.h"
|
#include "serene/reader/location.h"
|
||||||
#include "serene/serene.h"
|
#include "serene/serene.h"
|
||||||
#include "serene/symbol.hpp"
|
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
#define READER_LOG(...) \
|
#define READER_LOG(...) \
|
||||||
DEBUG_WITH_TYPE("READER", llvm::dbgs() << __VA_ARGS__ << "\n");
|
DEBUG_WITH_TYPE("READER", llvm::dbgs() << __VA_ARGS__ << "\n");
|
||||||
|
@ -45,15 +49,6 @@
|
||||||
namespace serene {
|
namespace serene {
|
||||||
namespace reader {
|
namespace reader {
|
||||||
|
|
||||||
class ReadError : public std::exception {
|
|
||||||
private:
|
|
||||||
char *message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ReadError(char *msg) : message(msg){};
|
|
||||||
const char *what() const throw() { return message; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Reader {
|
class Reader {
|
||||||
private:
|
private:
|
||||||
char current_char = ';'; // Some arbitary char to begin with
|
char current_char = ';'; // Some arbitary char to begin with
|
||||||
|
@ -65,19 +60,19 @@ private:
|
||||||
bool isValidForIdentifier(char c);
|
bool isValidForIdentifier(char c);
|
||||||
|
|
||||||
// The property to store the ast tree
|
// The property to store the ast tree
|
||||||
ast_tree ast;
|
exprs::ast ast;
|
||||||
ast_node readSymbol();
|
exprs::node readSymbol();
|
||||||
ast_node readNumber(bool);
|
exprs::node readNumber(bool);
|
||||||
ast_list_node readList();
|
exprs::node readList();
|
||||||
ast_node readExpr();
|
exprs::node readExpr();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Reader() : input_stream(""){};
|
Reader() : input_stream(""){};
|
||||||
Reader(const std::string);
|
Reader(const llvm::StringRef string);
|
||||||
|
|
||||||
void setInput(const std::string);
|
void setInput(const llvm::StringRef string);
|
||||||
|
|
||||||
std::unique_ptr<ast_tree> read();
|
llvm::Expected<exprs::ast> read();
|
||||||
|
|
||||||
// Dumps the AST data to stdout
|
// Dumps the AST data to stdout
|
||||||
void dumpAST();
|
void dumpAST();
|
||||||
|
@ -95,7 +90,7 @@ public:
|
||||||
// Dumps the AST data to stdout
|
// Dumps the AST data to stdout
|
||||||
void dumpAST();
|
void dumpAST();
|
||||||
|
|
||||||
std::unique_ptr<ast_tree> read();
|
llvm::Expected<exprs::ast> read();
|
||||||
|
|
||||||
~FileReader();
|
~FileReader();
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "mlir/IR/MLIRContext.h"
|
#include "mlir/IR/MLIRContext.h"
|
||||||
#include "serene/expr.hpp"
|
#include "serene/expr.hpp"
|
||||||
#include "serene/list.hpp"
|
#include "serene/list.hpp"
|
||||||
#include "serene/namespace.hpp"
|
#include "serene/namespace.h"
|
||||||
#include "serene/number.hpp"
|
#include "serene/number.hpp"
|
||||||
#include "serene/symbol.hpp"
|
#include "serene/symbol.hpp"
|
||||||
#include "llvm/ADT/ScopedHashTable.h"
|
#include "llvm/ADT/ScopedHashTable.h"
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include "mlir/IR/BuiltinOps.h"
|
#include "mlir/IR/BuiltinOps.h"
|
||||||
#include "mlir/IR/MLIRContext.h"
|
#include "mlir/IR/MLIRContext.h"
|
||||||
#include "serene/expr.hpp"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/sir/generator.hpp"
|
#include "serene/sir/generator.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
@ -41,12 +41,12 @@ private:
|
||||||
public:
|
public:
|
||||||
SIR();
|
SIR();
|
||||||
|
|
||||||
mlir::OwningModuleRef generate(::serene::Namespace *ns);
|
mlir::OwningModuleRef generate(serene::Namespace *ns);
|
||||||
|
|
||||||
~SIR();
|
~SIR();
|
||||||
};
|
};
|
||||||
|
|
||||||
void dumpSIR(ast_tree &t);
|
void dumpSIR(exprs::ast &t);
|
||||||
} // namespace sir
|
} // namespace sir
|
||||||
|
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/logger.hpp"
|
#include "serene/logger.hpp"
|
||||||
//#include "serene/namespace.hpp"
|
//#include "serene/namespace.h"
|
||||||
#include <llvm/IR/Module.h>
|
#include <llvm/IR/Module.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,16 @@ set(HEADER_LIST
|
||||||
"${INCLUDE_DIR}/serene/exprs/expression.h"
|
"${INCLUDE_DIR}/serene/exprs/expression.h"
|
||||||
"${INCLUDE_DIR}/serene/exprs/symbol.h"
|
"${INCLUDE_DIR}/serene/exprs/symbol.h"
|
||||||
"${INCLUDE_DIR}/serene/exprs/list.h"
|
"${INCLUDE_DIR}/serene/exprs/list.h"
|
||||||
|
"${INCLUDE_DIR}/serene/exprs/number.h"
|
||||||
|
|
||||||
# Reader
|
# Reader
|
||||||
"${INCLUDE_DIR}/serene/reader/reader.h"
|
"${INCLUDE_DIR}/serene/reader/reader.h"
|
||||||
"${INCLUDE_DIR}/serene/reader/location.h"
|
"${INCLUDE_DIR}/serene/reader/location.h"
|
||||||
|
"${INCLUDE_DIR}/serene/reader/errors.h"
|
||||||
|
|
||||||
|
"${INCLUDE_DIR}/serene/errors.h"
|
||||||
|
"${INCLUDE_DIR}/serene/errors/error.h"
|
||||||
|
"${INCLUDE_DIR}/serene/errors/errc.h"
|
||||||
|
|
||||||
|
|
||||||
"${INCLUDE_DIR}/serene/expr.hpp"
|
"${INCLUDE_DIR}/serene/expr.hpp"
|
||||||
|
@ -23,13 +29,15 @@ set(HEADER_LIST
|
||||||
"${INCLUDE_DIR}/serene/sir/sir.hpp"
|
"${INCLUDE_DIR}/serene/sir/sir.hpp"
|
||||||
"${INCLUDE_DIR}/serene/sir/dialect.hpp"
|
"${INCLUDE_DIR}/serene/sir/dialect.hpp"
|
||||||
"${INCLUDE_DIR}/serene/sir/generator.hpp"
|
"${INCLUDE_DIR}/serene/sir/generator.hpp"
|
||||||
"${INCLUDE_DIR}/serene/namespace.hpp")
|
"${INCLUDE_DIR}/serene/namespace.h")
|
||||||
|
|
||||||
# Make an automatic library - will be static or dynamic based on user setting
|
# Make an automatic library - will be static or dynamic based on user setting
|
||||||
add_library(serene
|
add_library(serene
|
||||||
exprs/expression.cpp
|
exprs/expression.cpp
|
||||||
exprs/symbol.cpp
|
exprs/symbol.cpp
|
||||||
exprs/list.cpp
|
exprs/list.cpp
|
||||||
|
exprs/number.cpp
|
||||||
|
|
||||||
|
|
||||||
serene.cpp
|
serene.cpp
|
||||||
symbol.cpp
|
symbol.cpp
|
||||||
|
@ -42,6 +50,7 @@ add_library(serene
|
||||||
# Reader
|
# Reader
|
||||||
reader/reader.cpp
|
reader/reader.cpp
|
||||||
reader/location.cpp
|
reader/location.cpp
|
||||||
|
reader/errors.cpp
|
||||||
|
|
||||||
# IR
|
# IR
|
||||||
sir/sir.cpp
|
sir/sir.cpp
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "serene/error.hpp"
|
#include "serene/error.hpp"
|
||||||
#include "serene/expr.hpp"
|
#include "serene/expr.hpp"
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/namespace.hpp"
|
#include "serene/namespace.h"
|
||||||
#include "serene/state.hpp"
|
#include "serene/state.hpp"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
|
@ -53,5 +53,6 @@ bool List::classof(const Expression *e) {
|
||||||
return e->getType() == ExprType::List;
|
return e->getType() == ExprType::List;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void List::append(node n) { elements.push_back(n); }
|
||||||
} // namespace exprs
|
} // namespace exprs
|
||||||
} // namespace serene
|
} // namespace serene
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Serene programming language.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "serene/exprs/number.h"
|
||||||
|
#include "llvm/Support/FormatVariadic.h"
|
||||||
|
|
||||||
|
namespace serene {
|
||||||
|
namespace exprs {
|
||||||
|
|
||||||
|
int64_t Number::toI64() {
|
||||||
|
// TODO: Handle float case as well
|
||||||
|
// TODO: Cache the value
|
||||||
|
return std::stoi(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
ExprType Number::getType() const { return ExprType::Number; };
|
||||||
|
|
||||||
|
std::string Number::toString() const {
|
||||||
|
return llvm::formatv("<Symbol [loc: {0} | {1}]: {2}>",
|
||||||
|
this->location.start.toString(),
|
||||||
|
this->location.end.toString(), this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Number::classof(const Expression *e) {
|
||||||
|
return e->getType() == ExprType::Number;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace exprs
|
||||||
|
} // namespace serene
|
|
@ -28,7 +28,6 @@
|
||||||
namespace serene {
|
namespace serene {
|
||||||
namespace exprs {
|
namespace exprs {
|
||||||
|
|
||||||
|
|
||||||
ExprType Symbol::getType() const { return ExprType::Symbol; };
|
ExprType Symbol::getType() const { return ExprType::Symbol; };
|
||||||
|
|
||||||
std::string Symbol::toString() const {
|
std::string Symbol::toString() const {
|
||||||
|
@ -37,7 +36,7 @@ std::string Symbol::toString() const {
|
||||||
this->location.end.toString(), this->name);
|
this->location.end.toString(), this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Symbol::classof(const Expression *e) {
|
bool Symbol::classof(const Expression *e) {
|
||||||
return e->getType() == ExprType::List;
|
return e->getType() == ExprType::List;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "serene/namespace.hpp"
|
#include "serene/namespace.h"
|
||||||
#include "serene/expr.hpp"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
@ -41,7 +41,7 @@ Namespace::Namespace(llvm::StringRef ns_name,
|
||||||
this->name = ns_name;
|
this->name = ns_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
ast_tree &Namespace::Tree() { return this->tree; }
|
exprs::ast &Namespace::Tree() { return this->tree; }
|
||||||
|
|
||||||
llvm::Optional<mlir::Value> Namespace::lookup(llvm::StringRef name) {
|
llvm::Optional<mlir::Value> Namespace::lookup(llvm::StringRef name) {
|
||||||
if (auto value = rootScope.lookup(name)) {
|
if (auto value = rootScope.lookup(name)) {
|
||||||
|
@ -51,7 +51,7 @@ llvm::Optional<mlir::Value> Namespace::lookup(llvm::StringRef name) {
|
||||||
return llvm::None;
|
return llvm::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
mlir::LogicalResult Namespace::setTree(ast_tree t) {
|
mlir::LogicalResult Namespace::setTree(exprs::ast &t) {
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
return mlir::failure();
|
return mlir::failure();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "serene/number.hpp"
|
#include "serene/number.hpp"
|
||||||
#include "serene/expr.hpp"
|
#include "serene/expr.hpp"
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/namespace.hpp"
|
#include "serene/namespace.h"
|
||||||
#include "serene/state.hpp"
|
#include "serene/state.hpp"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/* -*- C++ -*-
|
||||||
|
* Serene programming language.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "serene/reader/errors.h"
|
||||||
|
|
||||||
|
namespace serene {
|
||||||
|
namespace reader {
|
||||||
|
/// This one should be here, llvm's rules
|
||||||
|
char MissingFileError::ID;
|
||||||
|
}; // namespace reader
|
||||||
|
}; // namespace serene
|
|
@ -24,49 +24,48 @@
|
||||||
|
|
||||||
#include "serene/reader/reader.h"
|
#include "serene/reader/reader.h"
|
||||||
#include "serene/error.hpp"
|
#include "serene/error.hpp"
|
||||||
#include "serene/list.hpp"
|
#include "serene/exprs/list.h"
|
||||||
#include "serene/number.hpp"
|
#include "serene/exprs/number.h"
|
||||||
#include "serene/symbol.hpp"
|
#include "serene/exprs/symbol.h"
|
||||||
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/ErrorOr.h"
|
#include "llvm/Support/ErrorOr.h"
|
||||||
#include "llvm/Support/FormatVariadic.h"
|
#include "llvm/Support/FormatVariadic.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
|
|
||||||
namespace reader {
|
namespace reader {
|
||||||
Reader::Reader(const string input) { this->setInput(input); };
|
|
||||||
|
|
||||||
/**
|
Reader::Reader(const llvm::StringRef input) { this->setInput(input); };
|
||||||
* Set the input of the reader.
|
|
||||||
* @param input Set the input to the given string
|
/// Set the input of the reader.
|
||||||
*/
|
///\param input Set the input to the given string
|
||||||
void Reader::setInput(const string input) {
|
void Reader::setInput(const llvm::StringRef input) {
|
||||||
input_stream.write(input.c_str(), input.size());
|
input_stream.write(input.str().c_str(), input.size());
|
||||||
};
|
};
|
||||||
|
|
||||||
Reader::~Reader() { READER_LOG("Destroying the reader"); }
|
Reader::~Reader() { READER_LOG("Destroying the reader"); }
|
||||||
|
|
||||||
/**
|
/// Return the next character in the buffer and moves the location.
|
||||||
* Return the next character in the buffer.
|
///\param skip_whitespace If true it will skip whitespaces and EOL chars
|
||||||
* @param skip_whitespace If true it will skip whitespaces and EOL chars
|
/// \return next char in the buffer.
|
||||||
*/
|
|
||||||
char Reader::getChar(bool skip_whitespace) {
|
char Reader::getChar(bool skip_whitespace) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char c = input_stream.get();
|
char c = input_stream.get();
|
||||||
|
|
||||||
this->current_char = c;
|
this->current_char = c;
|
||||||
|
|
||||||
|
// TODO: Handle the end of line with respect to the OS.
|
||||||
|
// increase the current position in the buffer with respect to the end
|
||||||
|
// of line.
|
||||||
inc_location(current_location, c == '\n');
|
inc_location(current_location, c == '\n');
|
||||||
|
|
||||||
if (skip_whitespace == true && isspace(c)) {
|
if (skip_whitespace == true && isspace(c)) {
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return c;
|
return c;
|
||||||
|
@ -74,12 +73,15 @@ char Reader::getChar(bool skip_whitespace) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Moves back the location by one char. Basically unreads the last character.
|
||||||
void Reader::ungetChar() {
|
void Reader::ungetChar() {
|
||||||
input_stream.unget();
|
input_stream.unget();
|
||||||
// The char that we just unget
|
// The char that we just unget
|
||||||
dec_location(current_location, this->current_char == '\n');
|
dec_location(current_location, this->current_char == '\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A predicate function indicating whether the given char `c` is a valid
|
||||||
|
/// char for the starting point of a symbol or not.
|
||||||
bool Reader::isValidForIdentifier(char c) {
|
bool Reader::isValidForIdentifier(char c) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '!':
|
case '!':
|
||||||
|
@ -110,7 +112,7 @@ bool Reader::isValidForIdentifier(char c) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_node Reader::readNumber(bool neg) {
|
exprs::node Reader::readNumber(bool neg) {
|
||||||
std::string number(neg ? "-" : "");
|
std::string number(neg ? "-" : "");
|
||||||
bool floatNum = false;
|
bool floatNum = false;
|
||||||
bool empty = false;
|
bool empty = false;
|
||||||
|
@ -141,13 +143,13 @@ ast_node Reader::readNumber(bool neg) {
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
ungetChar();
|
ungetChar();
|
||||||
loc.end = current_location;
|
loc.end = current_location;
|
||||||
return makeNumber(loc, number, neg, floatNum);
|
return exprs::make<exprs::Number>(loc, number, neg, floatNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
ast_node Reader::readSymbol() {
|
exprs::node Reader::readSymbol() {
|
||||||
bool empty = true;
|
bool empty = true;
|
||||||
char c = getChar(false);
|
char c = getChar(false);
|
||||||
|
|
||||||
|
@ -186,16 +188,15 @@ ast_node Reader::readSymbol() {
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
ungetChar();
|
ungetChar();
|
||||||
loc.end = current_location;
|
loc.end = current_location;
|
||||||
return makeSymbol(loc, sym);
|
return exprs::make<exprs::Symbol>(loc, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: it should never happens
|
// TODO: it should never happens
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// std::unique_ptr<List> list
|
exprs::node Reader::readList() {
|
||||||
ast_list_node Reader::readList() {
|
auto list = exprs::makeAndCast<exprs::List>(current_location);
|
||||||
auto list = makeList(current_location);
|
|
||||||
|
|
||||||
char c = getChar(true);
|
char c = getChar(true);
|
||||||
assert(c == '(');
|
assert(c == '(');
|
||||||
|
@ -210,7 +211,7 @@ ast_list_node Reader::readList() {
|
||||||
throw ReadError(const_cast<char *>("EOF reached before closing of list"));
|
throw ReadError(const_cast<char *>("EOF reached before closing of list"));
|
||||||
case ')':
|
case ')':
|
||||||
list_terminated = true;
|
list_terminated = true;
|
||||||
list->location->end = current_location;
|
list->location.end = current_location;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -222,9 +223,9 @@ ast_list_node Reader::readList() {
|
||||||
} while (!list_terminated);
|
} while (!list_terminated);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
};
|
||||||
|
|
||||||
ast_node Reader::readExpr() {
|
exprs::node Reader::readExpr() {
|
||||||
char c = getChar(false);
|
char c = getChar(false);
|
||||||
READER_LOG("CHAR: " << c);
|
READER_LOG("CHAR: " << c);
|
||||||
|
|
||||||
|
@ -241,9 +242,9 @@ ast_node Reader::readExpr() {
|
||||||
default:
|
default:
|
||||||
return readSymbol();
|
return readSymbol();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
std::unique_ptr<ast_tree> Reader::read() {
|
llvm::Expected<exprs::ast> Reader::read() {
|
||||||
char c = getChar(true);
|
char c = getChar(true);
|
||||||
|
|
||||||
while (c != EOF) {
|
while (c != EOF) {
|
||||||
|
@ -255,18 +256,25 @@ std::unique_ptr<ast_tree> Reader::read() {
|
||||||
c = getChar(true);
|
c = getChar(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_unique<ast_tree>(this->ast);
|
return this->ast;
|
||||||
}
|
};
|
||||||
|
|
||||||
void Reader::dumpAST() {
|
void Reader::dumpAST() {
|
||||||
ast_tree ast = *this->read();
|
auto maybeAst = read();
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
for (auto &node : ast) {
|
|
||||||
result = fmt::format("{0} {1}", result, node->dumpAST());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ast_tree> FileReader::read() {
|
if (!maybeAst) {
|
||||||
|
throw maybeAst.takeError();
|
||||||
|
}
|
||||||
|
|
||||||
|
exprs::ast ast = *maybeAst;
|
||||||
|
|
||||||
|
for (auto &node : ast) {
|
||||||
|
result = llvm::formatv("{0} {1}", result, node->toString());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
llvm::Expected<exprs::ast> FileReader::read() {
|
||||||
|
|
||||||
// TODO: Add support for relative path as well
|
// TODO: Add support for relative path as well
|
||||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
|
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileOrErr =
|
||||||
|
@ -276,7 +284,7 @@ std::unique_ptr<ast_tree> FileReader::read() {
|
||||||
llvm::errs() << "Could not open input file: " << EC.message() << "\n";
|
llvm::errs() << "Could not open input file: " << EC.message() << "\n";
|
||||||
llvm::errs() << fmt::format("File: '{}'\n", file);
|
llvm::errs() << fmt::format("File: '{}'\n", file);
|
||||||
llvm::errs() << "Use absolute path for now\n";
|
llvm::errs() << "Use absolute path for now\n";
|
||||||
return nullptr;
|
return llvm::make_error<MissingFileError>(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
reader->setInput(fileOrErr.get()->getBuffer().str());
|
reader->setInput(fileOrErr.get()->getBuffer().str());
|
||||||
|
@ -285,17 +293,19 @@ std::unique_ptr<ast_tree> FileReader::read() {
|
||||||
|
|
||||||
void FileReader::dumpAST() {
|
void FileReader::dumpAST() {
|
||||||
auto maybeAst = this->read();
|
auto maybeAst = this->read();
|
||||||
ast_tree ast;
|
exprs::ast ast;
|
||||||
|
|
||||||
if (maybeAst) {
|
if (!maybeAst) {
|
||||||
ast = *maybeAst;
|
throw maybeAst.takeError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast = *maybeAst;
|
||||||
|
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
for (auto &node : ast) {
|
for (auto &node : ast) {
|
||||||
result = fmt::format("{0} {1}", result, node->dumpAST());
|
result = llvm::formatv("{0} {1}", result, node->toString());
|
||||||
}
|
}
|
||||||
cout << result << endl;
|
llvm::outs() << result << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
FileReader::~FileReader() {
|
FileReader::~FileReader() {
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include "serene/sir/sir.hpp"
|
#include "serene/sir/sir.hpp"
|
||||||
#include "mlir/IR/MLIRContext.h"
|
#include "mlir/IR/MLIRContext.h"
|
||||||
#include "serene/expr.hpp"
|
#include "serene/exprs/expression.h"
|
||||||
#include "serene/sir/dialect.hpp"
|
#include "serene/sir/dialect.hpp"
|
||||||
#include "serene/sir/generator.hpp"
|
#include "serene/sir/generator.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -41,7 +41,7 @@ mlir::OwningModuleRef SIR::generate(::serene::Namespace *ns) {
|
||||||
|
|
||||||
SIR::~SIR() {}
|
SIR::~SIR() {}
|
||||||
|
|
||||||
void dumpSIR(ast_tree &t) {
|
void dumpSIR(exprs::ast &t) {
|
||||||
auto ns = new ::serene::Namespace("user", llvm::None);
|
auto ns = new ::serene::Namespace("user", llvm::None);
|
||||||
|
|
||||||
SIR s{};
|
SIR s{};
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include "serene/state.hpp"
|
#include "serene/state.hpp"
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/namespace.hpp"
|
#include "serene/namespace.h"
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "serene/symbol.hpp"
|
#include "serene/symbol.hpp"
|
||||||
#include "serene/expr.hpp"
|
#include "serene/expr.hpp"
|
||||||
#include "serene/llvm/IR/Value.h"
|
#include "serene/llvm/IR/Value.h"
|
||||||
#include "serene/namespace.hpp"
|
#include "serene/namespace.h"
|
||||||
#include "serene/state.hpp"
|
#include "serene/state.hpp"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
|
@ -37,30 +37,9 @@ TEST_CASE("Public Expression API", "[expression]") {
|
||||||
|
|
||||||
REQUIRE(sym->getType() == ExprType::Symbol);
|
REQUIRE(sym->getType() == ExprType::Symbol);
|
||||||
REQUIRE(sym->toString() == "<Symbol [loc: 2:20:40 | 3:30:80]: example>");
|
REQUIRE(sym->toString() == "<Symbol [loc: 2:20:40 | 3:30:80]: example>");
|
||||||
};
|
|
||||||
|
|
||||||
TEST_CASE("List Expression", "[expression]") {
|
auto list = makeAndCast<List>(*range.get(), sym);
|
||||||
std::unique_ptr<reader::LocationRange> range(dummyLocation());
|
|
||||||
auto sym = make<Symbol>(*range.get(), llvm::StringRef("example"));
|
|
||||||
|
|
||||||
auto list = make<List>(*range.get());
|
|
||||||
auto list2 = make<List>(*range.get(), list);
|
|
||||||
auto list3 = make<List>(*range.get(), llvm::ArrayRef<node>{list, list2, sym});
|
|
||||||
|
|
||||||
REQUIRE(list->toString() == "<List [loc: 2:20:40 | 3:30:80]: ->");
|
|
||||||
REQUIRE(list->getType() == ExprType::List);
|
|
||||||
|
|
||||||
REQUIRE(
|
|
||||||
list2->toString() ==
|
|
||||||
"<List [loc: 2:20:40 | 3:30:80]: <List [loc: 2:20:40 | 3:30:80]: ->>");
|
|
||||||
REQUIRE(list3->toString() ==
|
|
||||||
"<List [loc: 2:20:40 | 3:30:80]: <List [loc: 2:20:40 | 3:30:80]: -> "
|
|
||||||
"<List [loc: 2:20:40 | 3:30:80]: <List [loc: 2:20:40 | 3:30:80]: "
|
|
||||||
"->> <Symbol [loc: 2:20:40 | 3:30:80]: example>>");
|
|
||||||
|
|
||||||
list->elements.push_back(sym);
|
|
||||||
|
|
||||||
REQUIRE(list->getType() == ExprType::List);
|
|
||||||
REQUIRE(list->toString() == "<List [loc: 2:20:40 | 3:30:80]: <Symbol [loc: "
|
REQUIRE(list->toString() == "<List [loc: 2:20:40 | 3:30:80]: <Symbol [loc: "
|
||||||
"2:20:40 | 3:30:80]: example>>");
|
"2:20:40 | 3:30:80]: example>>");
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* -*- C++ -*-
|
||||||
|
* Serene programming language.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../test_helpers.cpp.inc"
|
||||||
|
#include "serene/exprs/list.h"
|
||||||
|
#include "serene/exprs/symbol.h"
|
||||||
|
|
||||||
|
namespace serene {
|
||||||
|
namespace exprs {
|
||||||
|
|
||||||
|
TEST_CASE("List Expression", "[expression]") {
|
||||||
|
std::unique_ptr<reader::LocationRange> range(dummyLocation());
|
||||||
|
|
||||||
|
auto sym = make<Symbol>(*range.get(), llvm::StringRef("example"));
|
||||||
|
auto list = make<List>(*range.get());
|
||||||
|
auto list2 = make<List>(*range.get(), list);
|
||||||
|
auto list3 = make<List>(*range.get(), llvm::ArrayRef<node>{list, list2, sym});
|
||||||
|
|
||||||
|
REQUIRE(list->toString() == "<List [loc: 2:20:40 | 3:30:80]: ->");
|
||||||
|
REQUIRE(list->getType() == ExprType::List);
|
||||||
|
|
||||||
|
REQUIRE(
|
||||||
|
list2->toString() ==
|
||||||
|
"<List [loc: 2:20:40 | 3:30:80]: <List [loc: 2:20:40 | 3:30:80]: ->>");
|
||||||
|
REQUIRE(list3->toString() ==
|
||||||
|
"<List [loc: 2:20:40 | 3:30:80]: <List [loc: 2:20:40 | 3:30:80]: -> "
|
||||||
|
"<List [loc: 2:20:40 | 3:30:80]: <List [loc: 2:20:40 | 3:30:80]: "
|
||||||
|
"->> <Symbol [loc: 2:20:40 | 3:30:80]: example>>");
|
||||||
|
|
||||||
|
auto l = llvm::dyn_cast<List>(list);
|
||||||
|
|
||||||
|
l.append(sym);
|
||||||
|
|
||||||
|
REQUIRE(list->getType() == ExprType::List);
|
||||||
|
REQUIRE(list->toString() == "<List [loc: 2:20:40 | 3:30:80]: <Symbol [loc: "
|
||||||
|
"2:20:40 | 3:30:80]: example>>");
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace exprs
|
||||||
|
} // namespace serene
|
Loading…
Reference in New Issue