/* CODE_GENERATE.PL */ /* Code generator -------------- This file returns the function code_generate( ProgramTree ) -> Code which implements code generation. It also exports the command code_generate( ProgramTree+, Code- ) which writes out the code to the current output stream, as well as various other diagnostics. */ code_generate( 'PROG'(Name,Declarations,Body) ) <- 'CODE'( Code, InitialStore ) where ( 'ENV'( _, _, VarEnv ) = environment( Declarations ) and Code = fixup( cg( Name, E , Body ) ) and InitialStore = fill( VarEnv ) ). test_code_generate( 'PROG'(Name,Declarations,Body), 'CODE'(Code,InitialStore) ) does do environment( Declarations, E ) and do write( 'Environment : ') and do write_environment(E) and do nl and do cg( Name, E, Body, Unfixed ) and do write( 'Unfixedup code : ') and do write(Unfixed) and do nl and do fixup( Unfixed, Code ) and do E = 'ENV'( _, _, VarEnv ) and do fill( VarEnv, InitialStore ). environment( 'DECLARATIONS'( Labels, Consts, Vars ) ) <- 'ENV'( label_environment( Labels ), constant_environment( Consts ), variable_environment( Vars, 1000 ) ). write_environment( 'ENV'( Labels, Consts, Vars ) ) does do write( Labels ) and do write(' ') and do portray_map( Consts ) and do write(' ') and do portray_map( Vars ). label_environment( _ ) <- 0. constant_environment( [] ) <- map. constant_environment( [ 'C'(Name,Value) | Rest ] ) <- map_update( constant_environment( Rest ), Name, Value ). variable_environment( [], Start ) <- map. variable_environment( [ 'V'(Name,boolean) | Rest ], Start ) <- map_update( variable_environment( Rest, Start+1 ), Name, 'LOC'(Start,1) ). variable_environment( [ 'V'(Name,integer) | Rest ], Start ) <- map_update( variable_environment( Rest, Start+2 ), Name, 'LOC'(Start,2) ). lookup_var( 'ENV'( LabelEnv, ConstEnv, VarEnv ), Var ) <- map_value( VarEnv, Var ). location( Env, Var ) <- Start where ( 'LOC'(Start,Width) = lookup_var( Env, Var ) ) if is_var( Env, Var ). location( Env, Var ) <- 'ERROR'. width( Env, Var ) <- Width where ( 'LOC'(Start,Width) = lookup_var( Env, Var ) ). lookup_const( 'ENV'( LabelEnv, ConstEnv, VarEnv ), Const ) <- map_value( ConstEnv, Const ). is_var( 'ENV'( LabelEnv, ConstEnv, VarEnv ), Var ) :- map_defined( VarEnv, Var ). is_const( 'ENV'( LabelEnv, ConstEnv, VarEnv ), Const ) :- map_defined( ConstEnv, Const ). cg( Name, Environment, Body ) <- cg_statementlist( Environment, Body ). cg_statementlist( Environment, [] ) <- [ ]. cg_statementlist( Environment, [ Statement | Rest ] ) <- cg_statement( Environment, Statement ) ++ cg_statementlist( Environment, Rest ). cg_statementlist( Environment, Statement ) <- cg_statement( Environment, Statement ). cg_statement( Environment, 'ASSIGN'(Variable,Expression) ) <- cg_expression( Environment, Expression ) ++ [ 'ERRORASSIGN' ] if ( atom(Variable) and not( is_var( Environment, Variable ) ) ). cg_statement( Environment, 'ASSIGN'(Variable,Expression) ) <- cg_expression( Environment, Expression ) ++ [ 'OP'( store, location(Environment,Variable) ) ] if ( atom(Variable) and width( Environment, Variable ) = 2 ). cg_statement( Environment, 'ASSIGN'(Variable,Expression) ) <- cg_expression( Environment, Expression ) ++ [ 'OP'( storebyte, location(Environment,Variable) ) ] if ( atom(Variable) and width( Environment, Variable ) = 1 ). cg_statement( Environment, 'GOTO'(L) ) <- [ 'OP'( goto, L ) ]. cg_statement( Environment, 'LABELLED'(L,S) ) <- [ 'LABEL'(L) ] ++ cg_statement( Environment, S ). cg_statement( Environment, 'IF'(Cond,Then) ) <- ( cg_expression( NewEnvironment, Cond ) ++ [ 'OP'( jump_if_false, L ) ] ++ cg_statementlist( NewEnvironment, Then ) ++ [ 'LABEL'(L) ] ) where new_label( Environment, NewEnvironment, L ). cg_statement( Environment, 'READ'(Variable) ) <- [ 'OP'( read ), 'OP'( storebyte, location(Environment,Variable) ) ] if ( atom(Variable) and width( Environment, Variable ) = 1 ). cg_statement( Environment, 'READ'(Variable) ) <- [ 'OP'( read ), 'OP'( store, location(Environment,Variable) ) ] if ( atom(Variable) and width( Environment, Variable ) = 2 ). cg_statement( Environment, 'READ'(Variable) ) <- [ 'ERRREAD' ]. cg_statement( Environment, 'WRITE'('STR'(V)) ) <- cg_string( Environment, V ) ++ [ 'OP'( writestring ) ]. cg_statement( Environment, 'WRITE'(V) ) <- cg_expression( Environment, V ) ++ [ 'OP'( write ) ]. cg_statement( Environment, 'LIST'(S) ) <- cg_statementlist( Environment, S ). cg_statement( Environment, _ ) <- [ 'ERRSTMT' ]. cg_expression( Environment, true ) <- [ 'OP'( loadconst, 1 ) ]. cg_expression( Environment, false ) <- [ 'OP'( loadconst, 0 ) ]. cg_expression( Environment, I ) <- [ 'OP'( loadconst, I ) ] if integer( I ). cg_expression( Environment, Var ) <- [ 'OP'( loadbyte, location( Environment, Var ) ) ] if ( atom(Var) and width( Environment, Var ) = 1 ). cg_expression( Environment, Var ) <- [ 'OP'( load, location( Environment, Var ) ) ] if ( atom(Var) and width( Environment, Var ) = 2 ). cg_expression( Environment, Const ) <- cg_expression( Environment, lookup_const(Environment,Const) ) if ( atom(Const) and is_const( Environment, Const ) ). cg_expression( Environment, Const ) <- [ 'ERRID' ] if atom(Const). cg_expression( Environment, 'E'((=),E1,E2) ) <- cg_expression(Environment,E1) ++ cg_expression(Environment,E2) ++ [ 'OP'( eq ) ]. cg_expression( Environment, 'E'((<>),E1,E2) ) <- cg_expression(Environment,E1) ++ cg_expression(Environment,E2) ++ [ 'OP'( eq ), 'OP'( not ) ] . cg_expression( Environment, 'E'(+,E1,E2) ) <- cg_expression(Environment,E1) ++ cg_expression(Environment,E2) ++ [ 'OP'( add ) ]. cg_expression( Environment, 'E'(-,E1,E2) ) <- cg_expression(Environment,E1) ++ cg_expression(Environment,E2) ++ [ 'OP'( sub ) ]. cg_expression( Environment, 'E'(*,E1,E2) ) <- cg_expression(Environment,E1) ++ cg_expression(Environment,E2) ++ [ 'OP'( mult ) ]. cg_expression( Environment, 'E'(/,E1,E2) ) <- cg_expression(Environment,E1) ++ cg_expression(Environment,E2) ++ [ 'OP'( div ) ]. cg_expression( Environment, 'E'(and,E1,E2) ) <- cg_expression(Environment,E1) ++ cg_expression(Environment,E2) ++ [ 'OP'( logand ) ]. cg_expression( Environment, 'E'(or,E1,E2) ) <- cg_expression(Environment,E1) ++ cg_expression(Environment,E2) ++ [ 'OP'( logor ) ]. cg_expression( Environment, _ ) <- [ 'ERREXPR' ]. cg_string( Environment, Str ) <- cg_string_1( Environment, name(Str) ) ++ [ 'OP'( loadconst, listlength(name(Str)) ) ]. cg_string_1( Environment, [] ) <- []. cg_string_1( Environment, [C1|Cn] ) <- cg_string_1( Environment, Cn ) ++ [ 'OP'( loadconst, C1 ) ]. listlength( [] ) <- 0. listlength( [_|T] ) <- listlength( T ) + 1. /* For generating internal labels. */ new_label( 'ENV'(LastInternal,Consts,Vars), 'ENV'(NextInternal,Consts,Vars), NextInternal ) if NextInternal = LastInternal - 1. fixup( Code ) <- fixup_labels( Code, allocate_addresses( Code ) ). allocate_addresses( Code ) <- allocate1( Code, map, 0 ). allocate1( [], Map, Loc ) <- Map. allocate1( [ 'LABEL'(L) | Rest ], Map, Loc ) <- allocate1( Rest, map_update( Map, L, Loc ), Loc ). allocate1( [ Instruction | Rest ], Map, Loc ) <- allocate1( Rest, Map, Loc+width(Instruction) ). width( 'OP'(_) ) <- 2. width( 'OP'(_,_) ) <- 4. width( _ ) <- 0. fixup_labels( [], Addresses ) <- []. fixup_labels( [ 'OP'(GOTO,L) | Rest ], Addresses ) <- [ 'OP'( GOTO, map_value(Addresses,L) ) ] ++ fixup_labels( Rest, Addresses ) if is_jump( GOTO ) and map_defined( Addresses, L ). fixup_labels( [ 'OP'(GOTO,L) | Rest ], Addresses ) <- [ 'ERRGOTO' ] ++ fixup_labels( Rest, Addresses ) if is_jump( GOTO ). fixup_labels( [ 'LABEL'(L) | Rest ], Addresses ) <- [ 'LABEL'( map_value(Addresses,L) ) ] ++ fixup_labels( Rest, Addresses ) if map_defined( Addresses, L ). fixup_labels( [ 'LABEL'(L) | Rest ], Addresses ) <- [ 'ERRLBL' ] ++ fixup_labels( Rest, Addresses ). fixup_labels( [ Other | Rest ], Addresses ) <- [ Other ] ++ fixup_labels( Rest, Addresses ). is_jump( goto ). is_jump( jump_if_false ). fill( VarEnv ) <- fill1( map_range( VarEnv ) ). fill1( [] ) <- map. fill1( [ 'LOC'(Start,1) | Rest ] ) <- map_update( fill1( Rest ), Start, 255 ). fill1( [ 'LOC'(Start,2) | Rest ] ) <- map_update( map_update( fill1(Rest), Start, 255 ), Start+1, 255 ). 'OP'( Op ) <- q( 'OP'( Op ) ). 'OP'( Op, Operand ) <- q( 'OP'( Op, Operand ) ). 'LABEL'( Label ) <- q( 'LABEL'( Label ) ). 'ENV'( E1, E2, E3 ) <- q( 'ENV'( E1, E2, E3 ) ). 'LOC'( Start, Width ) <- q( 'LOC'( Start, Width ) ). 'CODE'( Code, Store ) <- q( 'CODE'( Code, Store ) ).