1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-15 23:04:09 +02:00
Beef/BeefTools/RandoCode/src/Program.bf

1242 lines
41 KiB
Beef

using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Threading.Tasks;
using System.Threading;
using Beefy.utils;
using System.Diagnostics;
namespace RandoCode
{
class Config
{
public int32 mTypeCount = 800; //20; //70 //300
public float mPrimitiveTypeChance = 0.0f;
//public float mStructPct = 0.2f; // Otherwise class
public float mStructPct = 0.0f;
public float mTypeComplexityPower = 3.0f;
public float mCreateGenericTypePct = 0.15f;
public float mSpecializedTypePower = 3.0f;
public float mUnspecializedTypeScalar = 10.0f;
public float mTypeDefPoolPower = 1.1f;
public float mTypeDefPoolOffset = 3.0f;
public float mTypeDefPoolScalar = 15.0f;
public float mFieldCountPower = 1.2f;
public float mFieldCountScalar = 12.0f;
public float mFieldStaticPct = 0.2f;
public float mVoidReturnPct = 0.6f;
public float mMethodCodeComplexityPower = 2.0f;
public float mMethodLengthScalar = 100.0f;
public float mMethodCountScalar = 300.0f; //2000.0f;//300.0f;
public float mAssignMemberPct = 0.3f;
public float mCreateLocalPct = 0.3f;
public float mParamCountPower = 3.0f;
public float mParamCountScalar = 5.0f;
public float mNewSpacespaceChance = 0.2f; // Chance a class will generate a new namespace vs using an existing one
public float mRootNamespaceChance = 0.1f; // Chance we will create root namespace vs adding to an existing one
}
class WordGroup
{
public List<String>[] mWords ~
{
for (var list in mWords)
DeleteContainerAndItems!(list);
delete _;
};
public HashSet<String> mUsedNames = new HashSet<String>() ~ DeleteContainerAndItems!(_);
public void GetName(float complexity, int parts, bool firstUpper, String outName)
{
int listNum = (int)(complexity * 3.999f);
var parts;
for (int tryCount = 0; true; tryCount++)
{
if (tryCount > 4)
parts++;
for (int namePartIdx = 0; namePartIdx < parts; namePartIdx++)
{
int idx = Program.sRand.Next(mWords[listNum].Count);
String namePart = scope String(mWords[listNum][idx]);
if ((firstUpper) || (namePartIdx > 0))
namePart[0] = namePart[0].ToUpper;
outName.Append(namePart);
}
if (mUsedNames.Contains(outName))
continue;
mUsedNames.Add(new String(outName));
return;
}
}
}
class LocalDef
{
public String mName ~ delete _;
public TypeDef mTypeDef;
}
class MethodDef
{
public String mName ~ delete _;
public int mParamCount;
public TypeDef mReturnType;
public List<LocalDef> mLocals = new List<LocalDef>() ~ DeleteContainerAndItems!(_);
public float mComplexity;
public int mStatementCount;
public bool mIsStatic;
}
class FieldDef
{
public String mName ~ delete _;
public TypeDef mTypeDef;
public bool mIsStatic;
}
class TypeDef
{
public NamespaceDef mNamespace;
public String mName ~ delete _;
public float mComplexity;
public bool mIsPrimitive;
public int mGenericParamIdx = -1;
public bool mIsStruct;
public int mUseCount;
public bool mIsSpecializedGeneric;
public bool mIsUnspecializedGeneric;
public List<TypeDef> mGenericParams ~ delete _;
public HashSet<NamespaceDef> mUsingNamespaces = new HashSet<NamespaceDef>() ~ delete _;
public List<FieldDef> mFields = new List<FieldDef>() ~ DeleteContainerAndItems!(_);
public List<MethodDef> mMethods = new List<MethodDef>() ~ DeleteContainerAndItems!(_);
public List<TypeDef> mTypeDefPool = new List<TypeDef>() ~ delete _; // We only refer to types in this pool
public void GetRootName(String outStr)
{
int ltPos = mName.IndexOf('<');
if (ltPos == -1)
{
outStr.Append(mName);
return;
}
outStr.Append(mName, 0, ltPos);
}
public void GetFullName(String outStr)
{
if (mNamespace == null)
{
outStr.Append(mName);
return;
}
mNamespace.GetFullName(outStr);
outStr.Append(".", mName);
}
}
class NamespaceDef
{
public NamespaceDef mParent;
public String mName ~ delete _;
public List<NamespaceDef> mChildren = new List<NamespaceDef>() ~ delete _;
public void GetFullName(String outStr)
{
if (mParent != null)
{
mParent.GetFullName(outStr);
outStr.Append(".");
}
outStr.Append(mName);
}
}
class Program
{
public static Random sRand ~ delete _;
int mSeed;
Config mConfig = new Config() ~ delete _;
String mBaseDir = new String("src") ~ delete _;
WordGroup mAdjList ~ delete _;
WordGroup mAdvList ~ delete _;
WordGroup mNounList ~ delete _;
WordGroup mVerbList ~ delete _;
bool mIsCompat = true;
TypeDef mCurTypeDef;
MethodDef mCurMethodDef;
List<NamespaceDef> mNamespaces = new List<NamespaceDef>() ~ DeleteContainerAndItems!(_);
TypeDef mVoidType ~ delete _;
List<TypeDef> mPrimitives = new List<TypeDef>() ~ DeleteContainerAndItems!(_);
List<TypeDef> mUserTypes = new List<TypeDef>() ~ DeleteContainerAndItems!(_);
List<TypeDef> mOtherTypes = new List<TypeDef>() ~ DeleteContainerAndItems!(_);
bool mVerbose;
int mLineCount;
bool mWroteLine;
String mQueuedText = new String() ~ delete _;
int mIndentCount;
int mStartIndentCount;
this()
{
//mSeed = (scope Random()).Next() % 100000;
mSeed = 92968;
Console.WriteLine("Random seed: {0}", mSeed);
sRand = new Random(mSeed);
}
WordGroup CreateWordGroup(String name)
{
WordGroup wordGroup = new WordGroup();
wordGroup.mWords = new List<String>[4];
for (int i = 0; i < 4; i++)
{
wordGroup.mWords[i] = new List<String>();
StreamReader file = scope StreamReader();
var filePath = scope String();
var exePath = scope String();
Environment.GetExecutableFilePath(exePath);
Path.GetDirectoryPath(exePath, filePath);
filePath.AppendF("/data/{0}{1}.txt", i + 1, name);
if (file.Open(filePath) case .Err)
continue;
while (!file.EndOfStream)
{
String line = scope String();
file.ReadLine(line);
bool isOnlyLetters = true;
for (char8 c in line.RawChars)
if (!c.IsLetter)
isOnlyLetters = false;
if (isOnlyLetters)
wordGroup.mWords[i].Add(new String(line));
}
}
return wordGroup;
}
void CreatePrimitives()
{
mVoidType = new TypeDef();
mVoidType.mName = new String("void");
mVoidType.mIsPrimitive = true;
String[] typeNames;
if (mIsCompat)
typeNames = scope:: .[] ( "int", "uint", "int", "float", "double" );
else
typeNames = scope:: .[] ( "int", "int16", "int32", "int64", "float", "double" );
for (var typeName in typeNames)
{
TypeDef typeDef = new TypeDef();
typeDef.mName = new String(typeName);
typeDef.mIsPrimitive = true;
mPrimitives.Add(typeDef);
}
}
float GetComplexity(float power)
{
return (float)Math.Pow(sRand.NextDouble(), power);
}
// Must return either a primitive type or a typedef whose name occurs alphabetically before the current type
TypeDef GetRandomTypeDef()
{
bool wantPrimitive = sRand.NextDouble() < mConfig.mPrimitiveTypeChance;
if ((!wantPrimitive) && (mUserTypes.Count > 0))
{
for (int tryCount = 0; tryCount < 4; tryCount++)
{
TypeDef checkTypeDef = mUserTypes[sRand.Next(mUserTypes.Count)];
if (checkTypeDef.mIsUnspecializedGeneric)
continue;
if (mCurTypeDef == null)
return checkTypeDef;
if (checkTypeDef.mName.CompareTo(mCurTypeDef.mName) < 0)
return checkTypeDef;
}
}
return mPrimitives[sRand.Next(mPrimitives.Count)];
}
TypeDef GetRandomPooledTypeDef()
{
return mCurTypeDef.mTypeDefPool[sRand.Next(mCurTypeDef.mTypeDefPool.Count)];
}
void GenerateType()
{
float typeComplexity = GetComplexity(mConfig.mTypeComplexityPower);
String className = new String();
mNounList.GetName(typeComplexity, 2, true, className);
TypeDef typeDef = new TypeDef();
typeDef.mName = className;
typeDef.mComplexity = typeComplexity;
mCurTypeDef = typeDef;
typeDef.mIsUnspecializedGeneric = sRand.NextDouble() < mConfig.mCreateGenericTypePct;
if (typeDef.mIsUnspecializedGeneric)
{
typeDef.mGenericParams = new List<TypeDef>();
int genericCount = (int)(1.0f + GetComplexity(3.0f) * 3.5f);
typeDef.mName.Append("<");
for (int genericIdx = 0; genericIdx < genericCount; genericIdx++)
{
TypeDef genericType = new TypeDef();
genericType.mGenericParamIdx = genericIdx;
genericType.mName = new String();
genericType.mName.Append("T");
mOtherTypes.Add(genericType);
mAdvList.GetName(0, 1, true, genericType.mName);
if (genericIdx > 0)
typeDef.mName.Append(", ");
typeDef.mName.Append(genericType.mName);
typeDef.mGenericParams.Add(genericType);
typeDef.mTypeDefPool.Add(genericType);
}
typeDef.mName.Append(">");
}
typeDef.mIsStruct = sRand.NextDouble() < mConfig.mStructPct;
if ((mNamespaces.Count == 0) || (sRand.NextDouble() < mConfig.mNewSpacespaceChance))
{
NamespaceDef newNamespace = new NamespaceDef();
newNamespace.mName = new String();
mAdjList.GetName((float)sRand.NextDouble(), 1, true, newNamespace.mName);
if ((mNamespaces.Count > 0) && (sRand.NextDouble() >= mConfig.mRootNamespaceChance))
{
NamespaceDef parentNamepace = mNamespaces[sRand.Next(mNamespaces.Count)];
parentNamepace.mChildren.Add(newNamespace);
newNamespace.mParent = parentNamepace;
}
mNamespaces.Add(newNamespace);
typeDef.mNamespace = newNamespace;
}
else
{
typeDef.mNamespace = mNamespaces[sRand.Next(mNamespaces.Count)];
}
mUserTypes.Add(typeDef);
}
void CreateTypePool(TypeDef typeDef, int poolSize)
{
for (int poolIdx = 0; poolIdx < poolSize; poolIdx++)
{
TypeDef poolTypeDef = GetRandomTypeDef();
ReferenceType(poolTypeDef);
poolTypeDef.mUseCount++;
typeDef.mTypeDefPool.Add(poolTypeDef);
}
}
void PopulateType(TypeDef typeDef)
{
mCurTypeDef = typeDef;
int poolSize = (int)(GetComplexity(mConfig.mTypeDefPoolPower) * mConfig.mTypeDefPoolScalar + mConfig.mTypeDefPoolOffset);
CreateTypePool(typeDef, poolSize);
int fieldCount = (int)(GetComplexity(mConfig.mFieldCountPower) * mConfig.mFieldCountScalar);
if (typeDef.mIsStruct)
fieldCount++;
for (int fieldIdx = 0; fieldIdx < fieldCount; fieldIdx++)
{
FieldDef fieldDef = new FieldDef();
fieldDef.mIsStatic = sRand.NextDouble() < mConfig.mFieldStaticPct;
// Just to make sure structs have at least one non-static member
if (fieldIdx == 0)
fieldDef.mIsStatic = false;
// Generic statics don't currently work
if (typeDef.mGenericParams != null)
fieldDef.mIsStatic = false;
if (fieldDef.mIsStatic)
{
fieldDef.mName = new String("s");
mNounList.GetName((float)sRand.NextDouble(), 1, true, fieldDef.mName);
}
else
{
fieldDef.mName = new String("m");
mNounList.GetName((float)sRand.NextDouble(), 1, true, fieldDef.mName);
}
fieldDef.mTypeDef = GetRandomPooledTypeDef();
typeDef.mFields.Add(fieldDef);
}
for (int methodIdx = 0; methodIdx < (int)(typeDef.mComplexity * mConfig.mMethodCountScalar); methodIdx++)
{
MethodDef methodDef = new MethodDef();
mCurMethodDef = methodDef;
float methodComplexity = GetComplexity(mConfig.mMethodCodeComplexityPower);
methodDef.mName = new String();
mVerbList.GetName(methodComplexity, 2, true, methodDef.mName);
methodDef.mComplexity = methodComplexity;
if (sRand.NextDouble() < mConfig.mVoidReturnPct)
methodDef.mReturnType = mVoidType;
else
methodDef.mReturnType = GetRandomPooledTypeDef();
int paramCount = (int)(GetComplexity(mConfig.mParamCountPower) * mConfig.mParamCountScalar);
for (int paramIdx = 0; paramIdx < paramCount; paramIdx++)
{
LocalDef localDef = new LocalDef();
localDef.mName = new String();
mNounList.GetName((float)sRand.NextDouble(), 1, false, localDef.mName);
localDef.mTypeDef = GetRandomPooledTypeDef();
methodDef.mLocals.Add(localDef);
methodDef.mParamCount++;
}
typeDef.mMethods.Add(methodDef);
}
MethodDef methodDef = new MethodDef();
methodDef.mIsStatic = true;
methodDef.mName = new String("Use");
methodDef.mReturnType = mVoidType;
typeDef.mMethods.Add(methodDef);
}
void DelTree(StringView dirName)
{
Debug.Assert(!dirName.IsEmpty);
if (!Directory.Exists(dirName))
return;
for (var subDir in Directory.EnumerateDirectories(dirName))
{
var filePath = scope String();
subDir.GetFilePath(filePath);
DelTree(filePath);
}
for (var file in Directory.EnumerateFiles(dirName))
{
var filePath = scope String();
file.GetFilePath(filePath);
if (filePath.EndsWith(".bf"))
{
File.Delete(filePath);
}
}
Directory.Delete(dirName);
}
FieldDef FindField(TypeDef inside, TypeDef wantTypeDef)
{
for (var field in inside.mFields)
{
if (field.mTypeDef == wantTypeDef)
{
if (field.mName == "sTar")
{
NOP!();
}
return field;
}
}
return null;
}
void FindData(TypeDef typeDef, String outStr)
{
for (int pass = 0; pass < 10; pass++)
{
int targetCategory = (int)(GetComplexity(1.0f) * 3);
if (targetCategory == 0) // 'This'
{
if (typeDef == mCurTypeDef)
{
outStr.Append("this");
return;
}
}
if ((targetCategory == 1) && (mCurTypeDef.mFields.Count > 0)) // Field
{
var fieldDef = mCurTypeDef.mFields[(int)(sRand.NextDouble() * mCurTypeDef.mFields.Count)];
if (fieldDef.mTypeDef == typeDef)
{
outStr.Append(fieldDef.mName);
return;
}
FieldDef subFieldDef = FindField(fieldDef.mTypeDef, typeDef);
if (subFieldDef != null)
{
if (subFieldDef.mName == "sTar")
{
}
if (subFieldDef.mIsStatic)
{
outStr.Append(fieldDef.mTypeDef.mName, ".", subFieldDef.mName);
return;
}
else
{
outStr.Append(fieldDef.mName, ".", subFieldDef.mName);
return;
}
}
}
if ((targetCategory == 2) && (mCurMethodDef.mLocals.Count > 0)) // Param / Local
{
var localDef = mCurMethodDef.mLocals[(int)(sRand.NextDouble() * mCurMethodDef.mLocals.Count)];
if (localDef.mTypeDef == typeDef)
{
outStr.Append(localDef.mName);
return;
}
FieldDef subFieldDef = FindField(localDef.mTypeDef, typeDef);
if (subFieldDef != null)
{
if (subFieldDef.mIsStatic)
{
outStr.Append(localDef.mTypeDef.mName, ".", subFieldDef.mName);
return;
}
else
{
outStr.Append(localDef.mName, ".", subFieldDef.mName);
return;
}
}
}
}
if (typeDef.mIsPrimitive)
{
outStr.Append("0");
return;
}
if ((!typeDef.mIsStruct) && (typeDef.mGenericParamIdx == -1))
{
outStr.Append("null");
return;
}
}
void WriteLine()
{
WriteLine("");
}
void WriteLine(String str)
{
mLineCount++;
mWroteLine = true;
for (int i = 0; i < mIndentCount; i++)
mQueuedText.Append("\t");
mQueuedText.Append(str, "\n");
}
void WriteLine(String str, params Object[] args)
{
WriteLine(scope String()..AppendF(str, params args));
}
void ReferenceType(TypeDef typeDef)
{
if (typeDef.mNamespace != null)
mCurTypeDef.mUsingNamespaces.Add(typeDef.mNamespace);
if (typeDef.mGenericParams != null)
{
for (var genericParam in typeDef.mGenericParams)
ReferenceType(genericParam);
}
}
String GetRandomTarget(out TypeDef targetType)
{
int targetCategory = (int)(GetComplexity(1.0f) * 3);
if (targetCategory == 0) // 'This'
{
targetType = mCurTypeDef;
return "";
}
if ((targetCategory == 1) && (mCurTypeDef.mFields.Count > 0)) // Field
{
var fieldDef = mCurTypeDef.mFields[(int)(sRand.NextDouble() * mCurTypeDef.mFields.Count)];
targetType = fieldDef.mTypeDef;
return fieldDef.mName;
}
if ((targetCategory == 2) && (mCurMethodDef.mLocals.Count > 0)) // Param / Local
{
var localDef = mCurMethodDef.mLocals[(int)(sRand.NextDouble() * mCurMethodDef.mLocals.Count)];
targetType = localDef.mTypeDef;
return localDef.mName;
}
targetType = null;
return null;
}
MethodDef GenerateMethodCall(String methodTarget, TypeDef targetType)
{
if (targetType != null)
{
if (targetType.mMethods.Count > 0)
{
var methodDef = targetType.mMethods[sRand.Next(targetType.mMethods.Count)];
if (methodDef.mIsStatic)
return null;
String[] targets = scope String[methodDef.mParamCount];
bool paramsMatch = true;
for (int paramIdx = 0; paramIdx < methodDef.mParamCount; paramIdx++)
{
var paramDef = methodDef.mLocals[paramIdx];
targets[paramIdx] = scope:: String();
FindData(paramDef.mTypeDef, targets[paramIdx]);
if (targets[paramIdx].IsEmpty)
paramsMatch = false;
}
if (paramsMatch)
{
String str = scope String();
bool didAssign = false;
if (sRand.NextDouble() < mConfig.mAssignMemberPct)
{
for (var fieldDef in mCurTypeDef.mFields)
{
if (fieldDef.mTypeDef == methodDef.mReturnType)
{
str.Append(fieldDef.mName, " = ");
didAssign = true;
break;
}
}
}
if ((!didAssign) && (sRand.NextDouble() < mConfig.mCreateLocalPct) && (methodDef.mReturnType != mVoidType))
{
ReferenceType(methodDef.mReturnType);
LocalDef localDef = new LocalDef();
localDef.mName = new String();
mNounList.GetName((float)sRand.NextDouble(), 1, false, localDef.mName);
localDef.mTypeDef = methodDef.mReturnType;
mCurMethodDef.mLocals.Add(localDef);
str.Append(localDef.mTypeDef.mName);
str.Append(" ");
str.Append(localDef.mName);
str.Append(" = ");
}
str.Append(methodTarget);
if (methodTarget != "")
str.Append(".");
str.Append(methodDef.mName);
str.Append("(");
for (int paramIdx = 0; paramIdx < methodDef.mParamCount; paramIdx++)
{
if (paramIdx > 0)
str.Append(", ");
str.Append(targets[paramIdx]);
}
str.Append(");");
WriteLine(str);
return methodDef;
}
}
}
return null;
}
MethodDef GenerateMethodCall()
{
TypeDef targetType = null;
String methodTarget = GetRandomTarget(out targetType);
return GenerateMethodCall(methodTarget, targetType);
}
void PopLocal()
{
var localDef = mCurMethodDef.mLocals.PopBack();
delete localDef;
}
void GetBoolExpression(String outStr)
{
TypeDef targetType;
String checkTarget = GetRandomTarget(out targetType);
if (checkTarget == null)
return;
if (checkTarget == "")
checkTarget = "this";
if (targetType.mIsStruct)
return;
if (targetType.mGenericParamIdx != -1)
return;
String rhs = scope String();
FindData(targetType, rhs);
if ((rhs != null) && (checkTarget != rhs))
{
outStr.Append(checkTarget, " != ", rhs);
return;
}
if (targetType.mIsPrimitive)
{
outStr.Append(checkTarget, " != 0");
return;
}
outStr.Append(checkTarget, " != null");
}
void GenerateMainBlock()
{
WriteLine("{");
mIndentCount++;
for (var pooledType in mUserTypes)
{
if (pooledType.mIsPrimitive)
continue;
if (pooledType.mIsUnspecializedGeneric)
continue;
if (pooledType.mName == "Program")
continue;
var line = scope String();
pooledType.GetFullName(line);
line.Append(".Use();");
WriteLine(line);
}
WriteLine("return 0;");
mIndentCount--;
WriteLine("}");
}
void GenerateUseBlock()
{
WriteLine("{");
mIndentCount++;
var line = scope String();
mCurTypeDef.GetFullName(line);
line.Append(" val = ");
if (!mCurTypeDef.mIsStruct)
line.Append("new ");
mCurTypeDef.GetFullName(line);
line.Append("();");
WriteLine(line);
for (var method in mCurTypeDef.mMethods)
{
if (method.mIsStatic)
continue;
line.Clear();
line.Append("val.", method.mName);
line.Append("(");
for (int argIdx < method.mParamCount)
{
if (argIdx > 0)
line.Append(", ");
line.Append("default");
}
line.Append(");");
WriteLine(line);
}
mIndentCount--;
WriteLine("}");
}
void GenerateBlock()
{
int prevLocalIdx = mCurMethodDef.mLocals.Count;
WriteLine("{");
mIndentCount++;
int methodLength = (int)(mCurMethodDef.mComplexity * mConfig.mMethodLengthScalar);
mWroteLine = false;
//while (true)
for (int stmtIdx < methodLength)
{
/*if (mCurMethodDef.mStatementCount > 0)
mCurMethodDef.mStatementCount--;
else if ((mWroteLine) && ((0.93 + mCurMethodDef.mComplexity * 0.03) < sRand.NextDouble()))
break;*/
if (sRand.NextDouble() < 0.5f)
{
GenerateMethodCall();
}
if (sRand.NextDouble() < 0.05f / mIndentCount)
{
String localVarName = new String()..AppendF("{0}", (char8)('i' + mIndentCount - 3));
String toVal = scope String();
FindData(mPrimitives[0], toVal);
if (toVal.IsEmpty)
{
toVal = scope:: String();
sRand.Next(1000).ToString(toVal);
}
LocalDef localDef = new LocalDef();
localDef.mName = localVarName;
localDef.mTypeDef = mPrimitives[0];
mCurMethodDef.mLocals.Add(localDef);
WriteLine("for (int {0} = 0; {0} < {1}; {0}++)", localVarName, toVal);
GenerateBlock();
PopLocal();
}
if (sRand.NextDouble() < 0.05f / mIndentCount)
{
String boolExpr = scope String();
GetBoolExpression(boolExpr);
if (!boolExpr.IsEmpty)
{
WriteLine("if ({0})", boolExpr);
GenerateBlock();
if (sRand.NextDouble() < 0.35f)
{
WriteLine("else");
GenerateBlock();
}
}
}
}
if (mIndentCount == mStartIndentCount + 1)
{
if (mCurMethodDef.mReturnType.mName != "void")
{
String retValName = scope String();
FindData(mCurMethodDef.mReturnType, retValName);
if (retValName.IsEmpty)
retValName.Append("default(", mCurMethodDef.mReturnType.mName, ")");
WriteLine("return {0};", retValName);
}
}
mIndentCount--;
WriteLine("}");
while (mCurMethodDef.mLocals.Count > prevLocalIdx)
PopLocal();
}
TypeDef FixType(TypeDef typeDef)
{
if (typeDef.mGenericParamIdx != -1)
return mCurTypeDef.mGenericParams[typeDef.mGenericParamIdx];
return typeDef;
}
void SpecializeType(TypeDef unspecializedType)
{
TypeDef specializedType = new TypeDef();
mCurTypeDef = specializedType;
specializedType.mName = new String();
unspecializedType.GetRootName(specializedType.mName);
specializedType.mIsSpecializedGeneric = true;
specializedType.mGenericParams = new List<TypeDef>();
specializedType.mIsStruct = unspecializedType.mIsStruct;
specializedType.mNamespace = unspecializedType.mNamespace;
specializedType.mName.Append("<");
for (int genericIdx = 0; genericIdx < unspecializedType.mGenericParams.Count; genericIdx++)
{
if (genericIdx > 0)
specializedType.mName.Append(", ");
var genericArg = GetRandomTypeDef();
//specializedType.mName.Append(genericArg.mName);
genericArg.GetFullName(specializedType.mName);
specializedType.mGenericParams.Add(genericArg);
}
specializedType.mName.Append(">");
for (var srcFieldDef in unspecializedType.mFields)
{
FieldDef destFieldDef = new FieldDef();
destFieldDef.mName = new String(srcFieldDef.mName);
destFieldDef.mTypeDef = FixType(srcFieldDef.mTypeDef);
destFieldDef.mIsStatic = srcFieldDef.mIsStatic;
specializedType.mFields.Add(destFieldDef);
}
for (var srcMethodDef in specializedType.mMethods)
{
MethodDef destMethodDef = new MethodDef();
destMethodDef.mName = new String(srcMethodDef.mName);
destMethodDef.mReturnType = FixType(srcMethodDef.mReturnType);
destMethodDef.mParamCount = srcMethodDef.mParamCount;
for (var localDef in srcMethodDef.mLocals)
{
LocalDef destLocalDef = new LocalDef();
destLocalDef.mName = new String(localDef.mName);
destLocalDef.mTypeDef = FixType(localDef.mTypeDef);
destMethodDef.mLocals.Add(destLocalDef);
}
specializedType.mMethods.Add(destMethodDef);
}
mUserTypes.Add(specializedType);
}
void ProgressStart()
{
if (cProgressSize > 0)
{
String str = scope String();
str.Append("[");
str.Append(' ', cProgressSize);
str.Append("]");
str.Append('\b', cProgressSize + 1);
Console.Write(str);
}
}
int mProgressIdx = 0;
void WriteProgress(float pct)
{
int progressIdx = (int)Math.Round(pct * cProgressSize);
while (progressIdx > mProgressIdx)
{
mProgressIdx++;
Console.Write("*");
}
}
const int cProgressSize = 30;
void Run()
{
CreatePrimitives();
DelTree(mBaseDir);
mAdjList = CreateWordGroup("adj");
mAdvList = CreateWordGroup("adv");
mNounList = CreateWordGroup("noun");
mVerbList = CreateWordGroup("verb");
for (int typeIdx = 0; typeIdx < mConfig.mTypeCount; typeIdx++)
GenerateType();
for (int typeIdx = 0; typeIdx < mUserTypes.Count; typeIdx++ )
{
TypeDef typeDef = mUserTypes[typeIdx];
if (typeDef.mIsUnspecializedGeneric)
{
PopulateType(typeDef);
int specializeCount = (int)(GetComplexity(mConfig.mSpecializedTypePower) * mConfig.mUnspecializedTypeScalar);
for (int specializedIdx = 0; specializedIdx < specializeCount; specializedIdx++)
SpecializeType(typeDef);
}
}
for (int typeIdx = 0; typeIdx < mUserTypes.Count; typeIdx++)
{
TypeDef typeDef = mUserTypes[typeIdx];
if ((!typeDef.mIsUnspecializedGeneric) && (!typeDef.mIsSpecializedGeneric))
PopulateType(typeDef);
}
{
TypeDef typeDef = new TypeDef();
typeDef.mName = new String("Program");
MethodDef methodDef = new MethodDef();
methodDef.mName = new String("Main");
methodDef.mParamCount = 1;
var arrTypeDef = new TypeDef();
arrTypeDef.mName = new String("System.String[]");
mOtherTypes.Add(arrTypeDef);
LocalDef localDef = new LocalDef();
localDef.mName = new String("args");
localDef.mTypeDef = arrTypeDef;
methodDef.mLocals.Add(localDef);
methodDef.mStatementCount = mUserTypes.Count + mPrimitives.Count;
methodDef.mReturnType = mPrimitives[2];
methodDef.mIsStatic = true;
typeDef.mMethods.Add(methodDef);
mCurTypeDef = typeDef;
CreateTypePool(typeDef, mUserTypes.Count + mPrimitives.Count);
mUserTypes.Add(typeDef);
}
if (!mVerbose)
ProgressStart();
int specializedTypes = 0;
int unspecializedTypes = 0;
for (var typeDef in mUserTypes)
UserTypeBlock:
{
var typeFullName = scope String();
typeDef.GetFullName(typeFullName);
if (typeDef.mIsSpecializedGeneric)
{
specializedTypes++;
if (mVerbose)
Console.WriteLine("Skipping type: {0} uses: {1}", typeFullName, typeDef.mUseCount);
continue;
}
if (typeDef.mIsUnspecializedGeneric)
unspecializedTypes++;
if (mVerbose)
Console.WriteLine("Writing type: {0} uses: {1}", typeFullName, typeDef.mUseCount);
String directory = scope String();
String namespaceStr = scope String();
if (typeDef.mNamespace != null)
{
typeDef.mNamespace.GetFullName(namespaceStr);
directory.Append(mBaseDir, "/");
directory.Replace('.', '/');
}
else
{
directory.Append(mBaseDir);
}
//StringWriter StringWriter = new StringWriter();
//mFile = StringWriter;
String fullPath = scope String()..Append(directory, "/");
typeDef.GetRootName(fullPath);
fullPath.Append(".bf");
FileStream file = scope FileStream();
bool isOpen = false;
for (int i = 0; i < 500; i++)
{
Directory.CreateDirectory(directory).IgnoreError();
if (file.Create(fullPath) case .Ok)
{
isOpen = true;
break;
}
Thread.Sleep(10);
}
if (!isOpen)
Runtime.FatalError("Unable to create file");
StreamWriter streamWrite = scope .(file, Encoding.UTF8, 4096);
mCurTypeDef = typeDef;
//mFile = file;
mIndentCount = 0;
WriteLine("// RandoCode seed: {0}", mSeed);
WriteLine("#pragma warning disable 0168");
WriteLine();
if (!namespaceStr.IsEmpty)
{
WriteLine("namespace {0}", namespaceStr);
WriteLine("{");
mIndentCount++;
}
String typeStr = scope String();
if (typeDef.mIsStruct)
typeStr.Append("struct ");
else
typeStr.Append("class ");
typeStr.Append(typeDef.mName);
WriteLine(typeStr);
WriteLine("{");
mIndentCount++;
for (var fieldDef in typeDef.mFields)
{
String str = scope String("public ");
if (fieldDef.mIsStatic)
str.Append("static ");
str.Append(fieldDef.mTypeDef.mName);
str.Append(" ");
str.Append(fieldDef.mName);
str.Append(";");
WriteLine(str);
}
for (int methodIdx = 0; methodIdx < typeDef.mMethods.Count; methodIdx++)
{
WriteLine();
var methodDef = typeDef.mMethods[methodIdx];
mCurMethodDef = methodDef;
String str = scope String("public ");
if (methodDef.mIsStatic)
str.Append("static ");
str.Append(methodDef.mReturnType.mName);
str.Append(" ");
str.Append(methodDef.mName);
str.Append("(");
for (int paramIdx = 0; paramIdx < methodDef.mParamCount; paramIdx++)
{
if (paramIdx > 0)
str.Append(", ");
var paramDef = methodDef.mLocals[paramIdx];
str.Append(paramDef.mTypeDef.mName);
str.Append(" ");
str.Append(paramDef.mName);
}
str.Append(")");
if (typeDef.mIsStruct)
str.Append("mut ");
WriteLine(str);
mStartIndentCount = mIndentCount;
if (methodDef.mName == "Main")
GenerateMainBlock();
else if (methodDef.mName == "Use")
GenerateUseBlock();
else
GenerateBlock();
}
mIndentCount--;
WriteLine("}");
if (!namespaceStr.IsEmpty)
{
mIndentCount--;
WriteLine("}");
}
for (var namespaceDef in typeDef.mUsingNamespaces)
{
var namespaceName = scope String();
namespaceDef.GetFullName(namespaceName);
streamWrite.WriteLine("using {0};", namespaceName);
}
streamWrite.Write(mQueuedText);
mQueuedText.Clear();
file.Close();
if (!mVerbose)
WriteProgress(@typeDef.Index / (float)mUserTypes.Count);
}
if (!mVerbose)
Console.WriteLine("");
Console.WriteLine("Types: {0} UnspecializedGenerics: {1} SpecializedGenerics: {2} Lines: {3}", mUserTypes.Count, unspecializedTypes, specializedTypes, mLineCount);
}
void HandleConfig(String configPath)
{
StructuredData sd = scope StructuredData();
sd.Load(configPath);
sd.Get("TypeCount", ref mConfig.mTypeCount);
sd.Get("PrimitiveTypeChance", ref mConfig.mPrimitiveTypeChance);
sd.Get("StructPct", ref mConfig.mStructPct);
sd.Get("TypeComplexityPower", ref mConfig.mTypeComplexityPower);
sd.Get("CreateGenericTypePct", ref mConfig.mCreateGenericTypePct);
sd.Get("SpecializedTypePower", ref mConfig.mSpecializedTypePower);
sd.Get("UnspecializedTypeScalar", ref mConfig.mUnspecializedTypeScalar);
sd.Get("TypeDefPoolPower", ref mConfig.mTypeDefPoolPower);
sd.Get("TypeDefPoolOffset", ref mConfig.mTypeDefPoolOffset);
sd.Get("TypeDefPoolScalar", ref mConfig.mTypeDefPoolScalar);
sd.Get("FieldCountPower", ref mConfig.mFieldCountPower);
sd.Get("FieldCountScalar", ref mConfig.mFieldCountScalar);
sd.Get("FieldStaticPct", ref mConfig.mFieldStaticPct);
sd.Get("VoidReturnPct", ref mConfig.mVoidReturnPct);
sd.Get("MethodCodeComplexityPower", ref mConfig.mMethodCodeComplexityPower);
sd.Get("MethodLengthScalar", ref mConfig.mMethodLengthScalar);
sd.Get("MethodCountScalar", ref mConfig.mMethodCountScalar);
sd.Get("AssignMemberPct", ref mConfig.mAssignMemberPct);
sd.Get("CreateLocalPct", ref mConfig.mCreateLocalPct);
sd.Get("ParamCountPower", ref mConfig.mParamCountPower);
sd.Get("ParamCountScalar", ref mConfig.mParamCountScalar);
sd.Get("NewSpacespaceChance", ref mConfig.mNewSpacespaceChance);
sd.Get("RootNamespaceChance", ref mConfig.mRootNamespaceChance);
}
static void Main(String[] args)
{
if (args.Count == 0)
{
Console.WriteLine("Usage: RandoCode <configFile>");
return;
}
String cwd = scope String();
Directory.GetCurrentDirectory(cwd);
Program pg = new Program();
pg.HandleConfig(args[0]);
pg.Run();
delete pg;
}
}
}