imports and a data structure (any critique welcome)

Jonathan jdgall84 at gmail.com
Thu Dec 26 16:40:54 PST 2013


I come from Haskell, so please excuse any functional programming 
idiosyncracies I have :)

In Haskell, I have a datatype for representing so called terms 
which looks like:

     data Term = Var Char | Op Char [Term]

i.e. a Term is a variable (denoted by an Int) or an operation 
(whose name is also denoted by an int), applied to a list of its 
arguments.  For example,

     f(g(x,y),a(),x) is represented by Op 'f' [Op 'g' [Var 'x',Var 
'y'],Op 'a' [], Var 'x]

Now, the reason I am writing in D is twofold.  First, I want to 
learn the D language, and second I really need pointers to reduce 
certain complexities in the operations (Haskell does not have 
observable sharing).

Okay, so the first thing I need to do is represent this as a data 
structure in D.  My choices are to represent the structure as a 
class or as a struct.  I choose struct because it is simpler (in 
terms of what is going on), and because the entire program takes 
one struct and makes changes to it.

Here is my first attempt at the datastructure.

struct Term {
	enum NodeType
	{
		Var, Op
	}
	NodeType node;
	union TermBody
	{
		int VarName;
		struct OpSymbol
		{
			int ConsName;	
			Term*[] Subterms;
		}
		OpSymbol terms;
	}
	TermBody term;
	this(int nodeValue)
	{
		node = NodeType.Var;
		term.VarName = nodeValue;
	}
	this(int OpSymb,Term*[] otherTerms)
	{
		node = NodeType.Op;
		term.terms.ConsName = OpSymb;
		term.terms.Subterms = otherTerms;
	}
}

I strongly encourage you guys to try to destroy my datastructure 
and critique anything and everything about it!!

But for now I will move on.  As a sanity check, I want to make 
sure I can print this datastructure out.

string termToString(Term* term)
{
	if ((*term).node == Term.NodeType.Var)
	{
		return [convertNum((*term).term.VarName)];
	}
	else
	{
		string retString = 
[convertNum((*term).term.terms.ConsName),'('];
		retString ~= termToString((*term).term.terms.Subterms[0]);
		for(size_t i = 1; i < (*term).term.terms.Subterms.length;i++)
		{
			retString ~= ',';
			retString ~= termToString((*term).term.terms.Subterms[i]);
		}
		retString ~= ')';
		return retString;
	}
}

For now, convertNum is rather silly,

char convertNum(int x){
	switch(x)
	{
		case 1: return 'x';
		case 2: return 'y';
		case 3: return 'z';
		case 4: return 'f';
		case 5: return 'g';
		case 6: return 'h';
		default: return 'e';
	}
}


Okay, here is some code to produce a simple example of a 
datastructure:

Term makeExTerm(){
	Term var1 = Term(1);//x
	Term var2 = Term(2);//y
	Term var3 = Term(3);//z
	Term fxx = Term(4, [&var1,&var1]);//f(x,x)
	Term gfxxy = Term(5, [&fxx,&var2]);//g(f(x,x),y)
	Term hzg = Term(6, [&gfxxy,&gfxxy]);//h(g(f(x,x),y),g(f(x,x),y))
	return hzg;
}

Using the above, I wrote a test program,

void main(string[] args)
{
	Term exTerm = makeExTerm();
	string printable = termToString(&exTerm);
	writeln(printable);
	Term var = Term(219);
	(*exTerm.term.terms.Subterms[0]).term.terms.Subterms[0] = &var;
         // it is now  (and should be) h(g(e,y),g(e,y))
	string printable2 = termToString(&exTerm);
	writeln(printable2);
}

If I put this in a file, compile it (with ldc or gdc), and run 
it, everything works just superbly.

However, if I extract everything except main to a different file 
and import that file, compilation passes, but running gives a 
segmentation fault.  I ran the program in a debugger, and the 
first line of main passes no problem, we are able to construct 
the term.  I checked the memory, and everything seems to work 
just fine.  However, when I step into the second line of main, 
the call to termToString, I get the segfault.

Can anyone tell me what is going on?


More information about the Digitalmars-d-learn mailing list