## tdefs.pkg
# Compiled by:
#
src/lib/c-kit/src/parser/c-parser.sublib### "God may not play dice with the universe,
### but something strange is going on
### with the prime numbers."
###
### -- Paul Erdos
api Type_Defs {
add_tdef: String -> Void; # A string as a typename in current scope
add_no_tdef: String -> Void; # A string is not a typename,
# may hide typenames of outer scopes
check_tdef: String -> Bool; # is this string a typename in current context ?
reset: Void -> Void; # Clear all tables, needed if you are doing many files
trunc_to: Ref( Int ); # limited-width names ?
push_scope: Void -> Void; # entering a new scope in C
pop_scope: Void -> Void; # exiting the last scope
};
# We need a stack of tables to properly handle the scoping in typenames
# Remember, there are four type of things competing in the namespace of
# typenames:
# typenames, variables, functions and enum constants
# Once you enter a new scope, reuse of these names can hide previous
# uses.
# Also note that struct field names do not redefine names within their scope
# So, the following is legal:
# typedef int bar;
# struct h {
# bar bar;
# bar baz;
# };
stipulate
package qht = quickstring_hashtable; # quickstring_hashtable is from
src/lib/src/quickstring-hashtable.pkgherein
package type_defs
: (weak) Type_Defs # Type_Defs is from
src/lib/c-kit/src/parser/grammar/tdefs.pkg {
package parse_control= config::parse_control; # config is from
src/lib/c-kit/src/variants/ansi-c/config.pkg exception NOT_TYPE_DEF;
my trunc_to: Ref( Int )
= REF parse_control::symbol_length;
Item = Bool; # TRUE says typename, FALSE says else
my say_tdefs: Ref( Bool )
= REF TRUE;
my tdef_table: Ref( List( qht::Hashtable( Item ) ) )
= REF ([qht::make_hashtable { size_hint => 1024, not_found_exception => NOT_TYPE_DEF }]);
fun check_tdef (str)
=
{ s = substring (str, 0, *trunc_to) except substring = str;
#
name = quickstring__premicrothread::from_string s;
fun lookup (n, NIL)
=>
NULL;
lookup (n, fst ! rst)
=>
case (qht::find fst n)
THE x => THE (x);
_ => (lookup (n, rst));
esac;
end;
case (lookup (name, *tdef_table))
THE TRUE => *say_tdefs;
THE FALSE => FALSE;
NULL => FALSE;
esac;
};
fun push_scope ()
=
{ tdef_table := (qht::make_hashtable { size_hint => 1024, not_found_exception => NOT_TYPE_DEF }) ! *tdef_table;
();
};
fun pop_scope () # was just tl *tdefTable, but caused problems with mythryl-yacc error correction
=
case *tdef_table
[x] => (); # Don't change
(_ ! l) => (tdef_table := l);
NIL => ();
esac;
#
# Don't change; but we are in trouble here!
error_count = REF 0;
fun reset ()
=
{ tdef_table := [qht::make_hashtable { size_hint => 1024, not_found_exception => NOT_TYPE_DEF }];
error_count := 0;
};
# TBD: In the next two functions,
# it is an option to raise exception
# a syntax error, if there is a
# redefinition in the same scope,
# i.e., the topmost table XXX BUGGO FIXME
fun add_tdef str
=
{ s = substring (str, 0, *trunc_to)
except
substring = str;
name = quickstring__premicrothread::from_string s;
# Insert name in the top
# of tdefTable as a typename
#
case *tdef_table
x ! _ => qht::set x (name, TRUE);
NIL => { if (*error_count == 0)
print "Error: empty type def table (lexer), probably caused by syntax error";
# should be error::error, but don't have an error stream handy. XXX BUGGO FIXME
fi;
error_count := *error_count + 1;
};
esac;
};
fun add_no_tdef (str)
=
{
s = substring (str, 0, *trunc_to)
except
substring = str;
name = quickstring__premicrothread::from_string s;
# Insert name in the top of tdefTable as not a typename:
#
case *tdef_table
x ! _ => qht::set x (name, FALSE);
NIL => { if (*error_count == 0)
print "Error: empty type def table (lexer), probably caused by syntax error";
# should be error::error, but don't have an error stream handy. XXX BUGGO FIXME
fi;
error_count := *error_count + 1;
};
esac;
};
};
end;