mirror of
https://github.com/dbalsom/x86_microcode.git
synced 2026-06-23 13:17:20 +03:00
Initial 80386 microcode commit.
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
#include "alfe/main.h"
|
||||
|
||||
#ifndef INCLUDED_FUNCTION_H
|
||||
#define INCLUDED_FUNCTION_H
|
||||
|
||||
#include "alfe/type.h"
|
||||
#include "alfe/identifier.h"
|
||||
#include "alfe/concrete.h"
|
||||
|
||||
// This is not a real type - we can't do anything with it. A funco does not
|
||||
// in general have a type (or even a tyco, because we can't do kind checking).
|
||||
// However, OverloadedFunctionSet needs to be wrapped in a Value and placed in
|
||||
// a symbol table (e.g. in ConfigFile), so this is the stub type for that.
|
||||
template<class T> class FuncoTypeT : public NamedNullary<Type, FuncoTypeT<T>>
|
||||
{
|
||||
public:
|
||||
static String name() { return "@FunctionConstructor"; }
|
||||
};
|
||||
|
||||
template<class T> class FuncoT;
|
||||
typedef FuncoT<void> Funco;
|
||||
|
||||
template<class T> class FuncoT : public Handle
|
||||
{
|
||||
protected:
|
||||
class Body : public Handle::Body
|
||||
{
|
||||
public:
|
||||
virtual FunctionType type() const { return FuncoType(); };
|
||||
virtual Value evaluate(List<Value> arguments, Span span) const = 0;
|
||||
virtual Identifier identifier() const = 0;
|
||||
virtual bool argumentsMatch(List<Type> argumentTypes) const = 0;
|
||||
virtual int compareTo(Funco other) const
|
||||
{
|
||||
List<Tyco> fTycos = parameterTycos();
|
||||
List<Tyco> bTycos = other.parameterTycos();
|
||||
assert(fTycos.count() == bTycos.count());
|
||||
auto bIterator = bTycos.begin();
|
||||
int r = 0;
|
||||
for (auto fTyco : fTycos) {
|
||||
Tyco bTyco = *bIterator;
|
||||
Type fType = fTyco;
|
||||
Type bType = bTyco;
|
||||
if (fType.valid() && bType.valid()) {
|
||||
if (!fType.canConvertTo(bType))
|
||||
r |= 2;
|
||||
if (!bType.canConvertTo(fType))
|
||||
r |= 1;
|
||||
}
|
||||
else {
|
||||
// This is enough for Berapa's built-in concrete functions,
|
||||
// but eventually we'll want to generalize this.
|
||||
if (bTyco == ConcreteTyco() &&
|
||||
(fTyco == IntegerType() || fTyco == RationalType()))
|
||||
r |= 1;
|
||||
if (fTyco == ConcreteTyco() &&
|
||||
(bTyco == IntegerType() || bTyco == RationalType()))
|
||||
r |= 2;
|
||||
}
|
||||
++bIterator;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
virtual List<Tyco> parameterTycos() const = 0;
|
||||
virtual String toString() const { return type().toString(); }
|
||||
};
|
||||
const Body* body() const { return as<Body>(); }
|
||||
public:
|
||||
FuncoT() { }
|
||||
FuncoT(const Handle& other) : Handle(other) { }
|
||||
Value evaluate(List<Value> arguments, Span span) const
|
||||
{
|
||||
return body()->evaluate(arguments, span);
|
||||
}
|
||||
Identifier identifier() const { return body()->identifier(); }
|
||||
bool argumentsMatch(List<Type> argumentTypes) const
|
||||
{
|
||||
return body()->argumentsMatch(argumentTypes);
|
||||
}
|
||||
int compareTo(Funco other) const { return body()->compareTo(other); }
|
||||
String toString() const { return body()->toString(); }
|
||||
FunctionType type() const { return body()->type(); }
|
||||
List<Tyco> parameterTycos() const { return body()->parameterTycos(); }
|
||||
};
|
||||
|
||||
class Function : public Funco
|
||||
{
|
||||
public:
|
||||
Function(const Handle& other) : Funco(other) { }
|
||||
Function(const Funco& other) : Funco(to<Body>(other)) { }
|
||||
protected:
|
||||
class Body : public Funco::Body
|
||||
{
|
||||
public:
|
||||
bool argumentsMatch(List<Type> argumentTypes) const
|
||||
{
|
||||
return type().argumentsMatch(argumentTypes.begin());
|
||||
}
|
||||
List<Tyco> parameterTycos() const
|
||||
{
|
||||
List<Tyco> tycos;
|
||||
type().addParameterTycos(&tycos);
|
||||
return tycos;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<class T> class OverloadedFunctionSetT : public Handle
|
||||
{
|
||||
class Body : public Handle::Body
|
||||
{
|
||||
public:
|
||||
Body(Identifier identifier) : _identifier(identifier) { }
|
||||
void add(Funco funco) { _funcos.add(funco); }
|
||||
Value evaluate(List<Value> arguments, Span span) const
|
||||
{
|
||||
List<::Type> argumentTypes;
|
||||
for (auto i : arguments)
|
||||
argumentTypes.add(i.type());
|
||||
List<Funco> bestCandidates;
|
||||
for (auto f : _funcos) {
|
||||
if (!f.argumentsMatch(argumentTypes))
|
||||
continue;
|
||||
List<Funco> newBestCandidates;
|
||||
bool newBest = true;
|
||||
for (auto b : bestCandidates) {
|
||||
int r = f.compareTo(b);
|
||||
if (r == 2) {
|
||||
// b better than f
|
||||
newBest = false;
|
||||
break;
|
||||
}
|
||||
if (r != 1)
|
||||
newBestCandidates.add(b);
|
||||
}
|
||||
if (newBest) {
|
||||
bestCandidates = newBestCandidates;
|
||||
bestCandidates.add(f);
|
||||
}
|
||||
}
|
||||
for (auto f : bestCandidates) {
|
||||
for (auto b : bestCandidates) {
|
||||
int r = f.compareTo(b);
|
||||
if (r == 3) {
|
||||
span.throwError("Ambiguous function call of " +
|
||||
_identifier.toString() + " with argument types " +
|
||||
argumentTypesString(argumentTypes) +
|
||||
". Could be " + b.toString() + " or " +
|
||||
f.toString() + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestCandidates.count() == 0) {
|
||||
span.throwError("No matches for function " +
|
||||
_identifier.toString() + " with argument types " +
|
||||
argumentTypesString(argumentTypes) + ".");
|
||||
}
|
||||
// We have a choice of possible funcos here. Logically they should
|
||||
// be equivalent, but some may be more optimal. For now we'll just
|
||||
// choose the first one, but later we may want to try to figure out
|
||||
// which one is most optimal.
|
||||
auto i = *bestCandidates.begin();
|
||||
|
||||
List<Value> convertedArguments;
|
||||
if (Function(i).valid()) {
|
||||
List<Tyco> parameterTycos = i.parameterTycos();
|
||||
auto ii = parameterTycos.begin();
|
||||
for (auto a : arguments) {
|
||||
Type type = *ii;
|
||||
if (!type.valid()) {
|
||||
a.span().throwError("Function parameter's type "
|
||||
"constructor is not a type.");
|
||||
}
|
||||
convertedArguments.add(a.convertTo(type));
|
||||
++ii;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Funcos that are not functions don't get their arguments
|
||||
// converted.
|
||||
convertedArguments = arguments;
|
||||
}
|
||||
return i.evaluate(convertedArguments, span);
|
||||
}
|
||||
private:
|
||||
String argumentTypesString(List<::Type> argumentTypes) const
|
||||
{
|
||||
String s;
|
||||
bool needComma = false;
|
||||
for (auto t : argumentTypes) {
|
||||
if (needComma)
|
||||
s += ", ";
|
||||
needComma = true;
|
||||
s += t.toString();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
List<Funco> _funcos;
|
||||
Identifier _identifier;
|
||||
};
|
||||
Body* body() { return as<Body>(); }
|
||||
const Body* body() const { return as<Body>(); }
|
||||
public:
|
||||
OverloadedFunctionSetT(Identifier identifier)
|
||||
: Handle(create<Body>(identifier)) { }
|
||||
void add(Funco funco) { body()->add(funco); }
|
||||
static Type type() { return FuncoType(); }
|
||||
Value evaluate(List<Value> arguments, Span span) const
|
||||
{
|
||||
return body()->evaluate(arguments, span);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // INCLUDED_FUNCTION_H
|
||||
Reference in New Issue
Block a user