RM_F    = @rm_f@
PERL    = @perl@
PARROT  = ../../parrot@exe@

C_BUILTIN = src/builtin
TCL_LIB   = library
PMCBUILD  = $(PERL) @build_dir@/tools/build/dynpmc.pl
OPSBUILD  = $(PERL) @build_dir@/tools/build/dynoplibs.pl
DESTDIR   = @build_dir@/runtime/parrot/dynext
O         = @o@
PMCDIR    = src/pmc
OPSDIR    = src/ops
CLASSDIR  = src/class
LOAD_EXT  = @load_ext@

CC_INC     = @cc_inc@
CC_SHARED  = @cc_shared@
CFLAGS     = $(CC_INC) @ccflags@ @cc_debug@ @ccwarn@ @cc_hasjit@ @cg_flag@ @gc_flag@ $(CC_SHARED)
CC         = @cc@


PGE_DIR  = ../../compilers/pge
TGE_DIR  = ../../compilers/tge

# can't use $(wildcard) and friends for PMCS, as these have to be in 
# dependency order; with no duplicates. 
PMCS = \
 tclobject \
 tclstring \
 tclint \
 tclfloat \
 tcllist \
 tclarray \
 tcldict \
 tclproc

GENERATED_INLINES = \
 $(C_BUILTIN)/break.pir \
 $(C_BUILTIN)/continue.pir \
 $(C_BUILTIN)/eof.pir \
 $(C_BUILTIN)/exit.pir \
 $(C_BUILTIN)/flush.pir \
 $(C_BUILTIN)/for.pir \
 $(C_BUILTIN)/incr.pir \
 $(C_BUILTIN)/join.pir \
 $(C_BUILTIN)/llength.pir \
 $(C_BUILTIN)/lrange.pir \
 $(C_BUILTIN)/pwd.pir \
 $(C_BUILTIN)/set.pir \
 $(C_BUILTIN)/time.pir \
 $(C_BUILTIN)/while.pir

RUNTIME_PIR = $(addprefix runtime/builtin/,$(notdir $(wildcard languages/tcl/runtime/builtin/*.pir)))

DEPS = \
$(C_BUILTIN)/auto_execok.pir \
$(C_BUILTIN)/auto_load.pir \
$(C_BUILTIN)/cd.pir \
$(C_BUILTIN)/exec.pir \
$(C_BUILTIN)/expr.pir \
$(C_BUILTIN)/fconfigure.pir \
$(C_BUILTIN)/glob.pir \
$(C_BUILTIN)/interp.pir \
$(C_BUILTIN)/list.pir \
$(C_BUILTIN)/return.pir \
$(C_BUILTIN)/trace.pir \
$(C_BUILTIN)/update.pir \
runtime/conversions.pir \
runtime/list_to_string.pir \
runtime/string_to_list.pir \
runtime/variables.pir \
runtime/options.pir \
src/macros.pir \
src/returncodes.pir \
src/grammar/expr/expression.pir \
src/grammar/expr/functions.pir \
src/grammar/expr/parse.pir \
src/grammar/expr/operators.pir \
src/grammar/expr/past2pir.pir \
src/grammar/expr/pge2past.pir \
$(TCL_LIB)/parray.tcl \
$(RUNTIME_PIR)

all: tcl.pbc

tcl.pbc: $(PARROT) pmcs ops runtime/tcllib.pbc src/tclsh.pir
	$(PARROT) --output=tcl.pbc src/tclsh.pir

$(GENERATED_INLINES) : tools/gen_inline.pl

.SUFFIXES : .pir .tmt .pg .tg .tcl

.tmt.pir :
	$(PERL) tools/gen_inline.pl $< > $@

.tg.pir :
	$(PARROT) $(TGE_DIR)/tgc.pir --output=$@ $<

.pg.pir :
	$(PARROT) $(PGE_DIR)/pgc.pir --output=$@ $<

.pir.pbc :
    $(PARROT) --output=$@ $<

.tcl.pir :
	$(PARROT) tcl.pbc $< --pir > $@

CLASSES = \
  $(CLASSDIR)/tclconst.pir

pmcs:
	@cd $(PMCDIR) && $(PMCBUILD) generate $(PMCS)
	@cd $(PMCDIR) && $(PMCBUILD) compile $(PMCS)
	@cd $(PMCDIR) && $(PMCBUILD) linklibs $(PMCS)
	@cd $(PMCDIR) && $(PMCBUILD) copy "--destination=$(DESTDIR)" $(PMCS)

# THIS WAS COPIED FROM THE ROOT MAKEFILE
# Passing an empty argument in @ARGV to cc_flags.pl to indicate where extra -Is
# (etc) should go. Otherwise it will insert them after the first space, which
# makes life go horribly wrong if $(CC) contains spaces but can't have -I
# arguments (etc) injected in the middle.
# There is probably a better way to do this, but I can't work it out right now.
.c$(O) :   
	@$(PERL) ../../tools/dev/cc_flags.pl ../../CFLAGS $(CC) "" $(CFLAGS) -I@build_dir@@slash@include @cc_o_out@$@ -c $<

ops: src/binary$(O)
	@cd $(OPSDIR) && $(OPSBUILD) generate tcl
	@cd $(OPSDIR) && $(OPSBUILD) compile  tcl
	@cd $(OPSDIR) && $(OPSBUILD) linklibs tcl ../binary$(O)
	@cd $(OPSDIR) && $(OPSBUILD) copy "--destination=$(DESTDIR)" tcl

runtime/builtins.pir: $(GENERATED_INLINES) $(DEPS) tools/gen_builtins.pl
	$(PERL) tools/gen_builtins.pl > runtime/builtins.pir

runtime/tcllib.pbc: $(PARROT) runtime/tcllib.pir runtime/builtins.pir $(CLASSES)
	$(PARROT) --output=runtime/tcllib.pbc runtime/tcllib.pir

tclsh: $(PARROT) tcl.pbc
	$(PARROT) --gc-debug tcl.pbc

test:	tcl.pbc
	prove -r t

# Can only run a few of these cleanly with test_more at the moment.
# eventually, as the list of commented out tests is smaller, just
# run them all. For now - only run the ones that will report properly
# to the harness (and pass at least one test), or those that have dubious
# failure modes

RUNNABLE_TCL_TESTS = \
  t_tcl/append.t \
  t_tcl/appendComp.t \
  t_tcl/apply.t \
  t_tcl/basic.t \
  t_tcl/binary.t \
  t_tcl/cmdAH.t \
  t_tcl/cmdIL.t \
  t_tcl/cmdMZ.t \
  t_tcl/compExpr_old.t \
  t_tcl/compExpr.t \
  t_tcl/compile.t \
  t_tcl/concat.t \
  t_tcl/dict.t \
  t_tcl/env.t \
  t_tcl/error.t \
  t_tcl/eval.t \
  t_tcl/execute.t \
  t_tcl/expr_old.t \
  t_tcl/expr.t \
  t_tcl/fileName.t \
  t_tcl/for_old.t \
  t_tcl/for.t \
  t_tcl/foreach.t \
  t_tcl/format.t \
  t_tcl/get.t \
  t_tcl/if_old.t \
  t_tcl/if.t \
  t_tcl/incr_old.t \
  t_tcl/incr.t \
  t_tcl/info.t \
  t_tcl/ioCmd.t \
  t_tcl/join.t \
  t_tcl/lindex.t \
  t_tcl/linsert.t \
  t_tcl/list.t \
  t_tcl/listObj.t \
  t_tcl/llength.t \
  t_tcl/lrange.t \
  t_tcl/lrepeat.t \
  t_tcl/lreplace.t \
  t_tcl/lsearch.t \
  t_tcl/lset.t \
  t_tcl/lsetComp.t \
  t_tcl/namespace.t \
  t_tcl/namespace_old.t \
  t_tcl/package.t \
  t_tcl/parse.t \
  t_tcl/parseOld.t \
  t_tcl/platform.t \
  t_tcl/proc_old.t \
  t_tcl/proc.t \
  t_tcl/pwd.t \
  t_tcl/regexp.t \
  t_tcl/regexpComp.t \
  t_tcl/rename.t \
  t_tcl/scan.t \
  t_tcl/security.t \
  t_tcl/set_old.t \
  t_tcl/set.t \
  t_tcl/split.t \
  t_tcl/string.t \
  t_tcl/stringComp.t \
  t_tcl/subst.t \
  t_tcl/switch.t \
  t_tcl/unknown.t \
  t_tcl/uplevel.t \
  t_tcl/upvar.t \
  t_tcl/util.t \
  t_tcl/var.t \
  t_tcl/while_old.t \
  t_tcl/while.t

# These tests parse, or fail (or skip) every (or nearly every) test.
FAILING_TCL_TESTS = \
  t_tcl/assocd.t \
  t_tcl/case.t \
  t_tcl/chan.t \
  t_tcl/clock.t \
  t_tcl/cmdInfo.t \
  t_tcl/config.t \
  t_tcl/dcall.t \
  t_tcl/dstring.t \
  t_tcl/event.t \
  t_tcl/history.t \
  t_tcl/indexObj.t \
  t_tcl/init.t \
  t_tcl/interp.t \
  t_tcl/ioUtil.t \
  t_tcl/link.t \
  t_tcl/load.t \
  t_tcl/macOSXFCmd.t \
  t_tcl/main.t \
  t_tcl/misc.t \
  t_tcl/notify.t \
  t_tcl/obj.t \
  t_tcl/parseExpr.t \
  t_tcl/pid.t \
  t_tcl/pkg.t \
  t_tcl/registry.t \
  t_tcl/result.t \
  t_tcl/socket.t \
  t_tcl/source.t \
  t_tcl/stack.t \
  t_tcl/thread.t \
  t_tcl/tm.t \
  t_tcl/trace.t \
  t_tcl/unixFCmd.t \
  t_tcl/unixFile.t \
  t_tcl/unixNotfy.t \
  t_tcl/unload.t \
  t_tcl/utf.t \
  t_tcl/winConsole.t \
  t_tcl/winDde.t \
  t_tcl/winFCmd.t \
  t_tcl/winNotify.t \
  t_tcl/winPipe.t \
  t_tcl/winTime.t

DYING_TCL_TESTS = \
  t_tcl/async.t \
  t_tcl/autoMkindex.t \
  t_tcl/encoding.t \
  t_tcl/exec.t \
  t_tcl/fCmd.t \
  t_tcl/fileSystem.t \
  t_tcl/http.t \
  t_tcl/httpold.t \
  t_tcl/io.t \
  t_tcl/iogt.t \
  t_tcl/mathop.t \
  t_tcl/msgcat.t \
  t_tcl/macOSXLoad.t \
  t_tcl/opt.t \
  t_tcl/pkgMkIndex.t \
  t_tcl/reg.t \
  t_tcl/safe.t \
  t_tcl/stringObj.t \
  t_tcl/tcltest.t \
  t_tcl/timer.t \
  t_tcl/unixInit.t \
  t_tcl/winFile.t

tcl-test: t_tcl tcl.pbc
    # For now, just test the ones that ``work'' with test_more
	TEST_PROG_ARGS=-G prove $(RUNNABLE_TCL_TESTS)
t_tcl:
	$(PERL) tools/tcl_test.pl

devtest:
	cd t && $(PERL) -e 'use Test::Harness qw($$verbose runtests) ; $$Test::Harness::verbose=1;runtests(glob("*.t"))' && cd ..

CLEANERS = \
tcl.pbc \
runtime/builtins.pir \
"runtime/*.pbc" \
"$(CLASSDIR)/*.pbc" \
"$(PMCDIR)/pmc_*.h" \
"$(PMCDIR)/*_group.h" \
"$(PMCDIR)/*$(LOAD_EXT)" \
"$(PMCDIR)/*.dump" \
#CONDITIONED_LINE(ld_parrot_exe_def):"$(PMCDIR)/*.def" \
"$(PMCDIR)/*.c" \
"$(PMCDIR)/*$(O)" \
"$(PMCDIR)/*.exp" \
"$(PMCDIR)/*.ilk" \
"$(PMCDIR)/*.lib" \
"$(PMCDIR)/*.pdb" \
"t/*.pir" \
"t/*.tcl" \
src/grammar/expr/expression.pir \
src/grammar/expr/past2pir.pir \
src/grammar/expr/pge2past.pir \
$(GENERATED_INLINES) \
"$(OPSDIR)/*.c" \
"$(OPSDIR)/*.h" \
"src/*$(O)" \
"$(OPSDIR)/*$(O)" \
"$(OPSDIR)/*.bundle" \
"$(OPSDIR)/*.exp" \
"$(OPSDIR)/*.ilk" \
"$(OPSDIR)/*.lib" \
"$(OPSDIR)/*.pdb" \
"$(TCL_LIB)/*.pir"

# that last line should be cleaned up for x-platform.

clean:
	$(RM_F) $(CLEANERS)

distclean: clean
	$(RM_F) Makefile

