shithub: mc

Download patch

ref: 630d88d392d04d0d21ec626059341093307c1e1f
parent: 489c5febf900166636cc41d82b53191bcd2023e2
parent: bc0b3961de94fc33b42caca28e631cbfdf7eac72
author: akoshibe <[email protected]>
date: Tue Aug 5 20:12:03 EDT 2014

Merge branch 'master' of https://github.com/oridb/mc

--- a/6/isel.c
+++ b/6/isel.c
@@ -14,8 +14,7 @@
 #include "parse.h"
 #include "opt.h"
 #include "asm.h"
-
-#include "platform.h"
+#include "../config.h"
 
 /* string tables */
 char *insnfmts[] = {
--- a/6/platform.h
+++ /dev/null
@@ -1,9 +1,0 @@
-#if defined(__APPLE__) && defined(__MACH__)
-/* for OSX */
-#   define Asmcmd "as -g -o %s %s"
-#   define Symprefix "_"
-#else
-/* Default to linux */
-#   define Asmcmd "as -g -o %s %s"
-#   define Symprefix ""
-#endif
--- a/6/simp.c
+++ b/6/simp.c
@@ -12,8 +12,7 @@
 #include "parse.h"
 #include "opt.h"
 #include "asm.h"
-
-#include "platform.h" /* HACK. We need some platform specific code gen behavior. *sigh.* */
+#include "../config.h"
 
 
 /* takes a list of nodes, and reduces it (and it's subnodes) to a list
--- a/configure
+++ b/configure
@@ -37,12 +37,12 @@
 case $OS in
     *Linux*)
         echo '#define Asmcmd "as -g -o %s %s"' >> config.h
-        echo '#define Fprefix ""' >> config.h
+        echo '#define Symprefix ""' >> config.h
         echo 'export SYS=linux' >> config.mk
         ;;
     *Darwin*)
         echo '#define Asmcmd "as -g -o %s %s"' >> config.h
-        echo '#define Fprefix "_"' >> config.h
+        echo '#define Symprefix "_"' >> config.h
         echo 'export SYS=osx' >> config.mk
         ;;
     *FreeBSD*)
--- a/libstd/Makefile
+++ b/libstd/Makefile
@@ -43,6 +43,7 @@
     strjoin.myr \
     strsplit.myr \
     strstrip.myr \
+    swap.myr \
     sys.myr \
     try.myr \
     types.myr \
--- /dev/null
+++ b/libstd/swap.myr
@@ -1,0 +1,11 @@
+pkg std =
+	generic swap	: (a : @a#, b : @a# -> void)
+;;
+
+generic swap = {a : @a#, b : @a#
+	var t
+
+	t = a#
+	a# = b#
+	b# = t
+}
--- a/libstd/sys-freebsd.myr
+++ b/libstd/sys-freebsd.myr
@@ -11,6 +11,7 @@
 	type sockproto	= int64	/* socket protocol */
 	type sockfam	= uint8	/* socket family */
 	type filemode	= uint16
+	type filetype	= uint8
 
 	type clock = union
 		`Clockrealtime
@@ -109,11 +110,22 @@
 	type dirent = struct
 		fileno	: uint32
 		reclen	: uint16
-		type	: filetype
+		ftype	: filetype
 		namelen	: uint8
 		name	: byte[256]	
 	;;	
 
+	/* open options */
+	const Ordonly  	: fdopt = 0x0
+	const Owronly  	: fdopt = 0x1
+	const Ordwr    	: fdopt = 0x2
+	const Oappend  	: fdopt = 0x8
+	const Ocreat   	: fdopt = 0x200
+	const Onofollow	: fdopt = 0x100
+	const Ondelay  	: fdopt = 0x4
+	const Otrunc   	: fdopt = 0x400
+	const Odir	: fdopt = 0x20000
+
         /* stat modes */	
 	const Sifmt	: filemode = 0xf000
 	const Sififo	: filemode = 0x1000
@@ -124,6 +136,21 @@
 	const Siflnk	: filemode = 0xa000
 	const Sifsock 	: filemode = 0xc000
 
+	/* mmap protection */
+	const Mprotnone	: mprot = 0x0
+	const Mprotrd	: mprot = 0x1
+	const Mprotwr	: mprot = 0x2
+	const Mprotexec	: mprot = 0x4
+	const Mprotrw	: mprot = 0x3
+
+	/* mmap options */
+	const Mshared	: mopt = 0x1
+	const Mpriv	: mopt = 0x2
+	const Mfixed	: mopt = 0x10
+	const Mfile	: mopt = 0x0
+	const Manon	: mopt = 0x1000
+	const M32bit	: mopt = 0x80000
+
 	/* file types */
 	const Dtunknown	: filetype = 0
 	const Dtfifo	: filetype = 1
@@ -134,6 +161,31 @@
 	const Dtlnk	: filetype = 10
 	const Dtsock	: filetype = 12
 	const Dtwht	: filetype = 14
+
+	/* socket families. INCOMPLETE. */
+	const Afunspec	: sockfam = 0
+	const Afunix	: sockfam = 1
+	const Afinet	: sockfam = 2
+	const Afinet6	: sockfam = 28
+
+	/* socket types. */
+	const Sockstream	: socktype = 1
+	const Sockdgram		: socktype = 2
+	const Sockraw		: socktype = 3
+	const Sockrdm		: socktype = 4
+	const Sockseqpacket	: socktype = 5
+
+	/* network protocols */
+	const Ipproto_ip	: sockproto = 0
+	const Ipproto_icmp	: sockproto = 1
+	const Ipproto_tcp	: sockproto = 6
+	const Ipproto_udp	: sockproto = 17
+	const Ipproto_raw	: sockproto = 255
+
+	/* return value for a failed mapping */
+	const Mapbad	: byte# = -1 castto(byte#)
+
+	/* syscalls */
 	const Syssyscall                   : scno = 0
 	const Sysexit                      : scno = 1
 	const Sysfork                      : scno = 2
@@ -593,3 +645,123 @@
 	const uname 	: (buf : utsname# -> int)
 	const sysctl	: (mib : int[:], old : byte[:]#, new : byte[:] -> int)
 ;;
+
+extern const cstring	: (str : byte[:] -> byte#)
+extern const alloca	: (sz : size	-> byte#)
+extern const __cenvp : byte##
+
+/* process management */
+const exit	= {status;		syscall(Sysexit, status castto(int64))}
+const getpid	= {;			-> syscall(Sysgetpid, 1)}
+const kill	= {pid, sig;		-> syscall(Syskill, pid, sig)}
+const fork	= {;			-> syscall(Sysfork)}
+const wait4	= {pid, loc, opt, usage;	-> syscall(Syswait4, pid, loc, opt, usage)}
+const waitpid	= {pid, loc, opt;
+	-> wait4(pid, loc, opt, 0 castto(rusage#)) 
+}
+
+const execv	= {cmd, args
+	var p, cargs, i
+
+	/* of course we fucking have to duplicate this code everywhere,
+	* since we want to stack allocate... */
+	p = alloca((args.len + 1)*sizeof(byte#))
+	cargs = (p castto(byte##))[:args.len]
+	for i = 0; i < args.len; i++
+		cargs[i] = cstring(args[i])
+	;;
+	cargs[args.len] = 0 castto(byte#)
+	-> syscall(Sysexecve, cstring(cmd), p, __cenvp)
+}
+
+const execve	= {cmd, args, env
+	var cargs, cenv, i
+	var p
+
+	/* copy the args */
+	p = alloca((args.len + 1)*sizeof(byte#))
+	cargs = (p castto(byte##))[:args.len]
+	for i = 0; i < args.len; i++
+		cargs[i] = cstring(args[i])
+	;;
+	cargs[args.len] = 0 castto(byte#)
+
+	/*
+	 copy the env.
+	 of course we fucking have to duplicate this code everywhere,
+	 since we want to stack allocate... 
+	*/
+	p = alloca((env.len + 1)*sizeof(byte#))
+	cenv = (p castto(byte##))[:env.len]
+	for i = 0; i < env.len; i++
+		cenv[i] = cstring(env[i])
+	;;
+	cenv[env.len] = 0 castto(byte#)
+
+	-> syscall(Sysexecve, cstring(cmd), p, cenv)
+}
+
+/* fd manipulation */
+const open	= {path, opts;		-> syscall(Sysopen, cstring(path), opts, 0o777) castto(fd)}
+const openmode	= {path, opts, mode;	-> syscall(Sysopen, cstring(path), opts, mode) castto(fd)}
+const close	= {fd;			-> syscall(Sysclose, fd)}
+const creat	= {path, mode;		-> openmode(path, Ocreat | Otrunc | Owronly, mode) castto(fd)}
+const read	= {fd, buf;		-> syscall(Sysread, fd, buf castto(byte#), buf.len castto(size)) castto(size)}
+const write	= {fd, buf;		-> syscall(Syswrite, fd, buf castto(byte#), buf.len castto(size)) castto(size)}
+const lseek	= {fd, off, whence;	-> syscall(Syslseek, fd, off, whence)}
+const stat	= {path, sb;		-> syscall(Sysstat, cstring(path), sb)}
+const lstat	= {path, sb;		-> syscall(Syslstat, cstring(path), sb)}
+const fstat	= {fd, sb;		-> syscall(Sysfstat, fd, sb)}
+const mkdir	= {path, mode;		-> syscall(Sysmkdir, cstring(path), mode) castto(int64)}
+const ioctl	= {fd, req, args
+	var arg : byte#
+	var ap
+
+	ap = vastart(&args)
+	(arg, ap) = vanext(ap)
+	-> syscall(Sysioctl, fd, req, arg) castto(int64)
+}
+const getdirentries64	= {fd, buf, basep;	-> syscall(Sysgetdirentries, fd, buf castto(byte#), buf.len castto(size), basep)}
+
+/* networking */
+const socket	= {dom, stype, proto;	-> syscall(Syssocket, dom castto(int64), stype, proto) castto(fd) }
+const connect	= {sock, addr, len;	-> syscall(Sysconnect, sock, addr, len) castto(int)}
+const accept	= {sock, addr, len;	-> syscall(Sysaccept, sock, addr, len) castto(fd)}
+const listen	= {sock, backlog;	-> syscall(Syslisten, sock, backlog castto(int64)) castto(int)}
+const bind	= {sock, addr, len;	-> syscall(Sysbind, sock, addr, len) castto(int)}
+
+/* memory management */
+const munmap	= {addr, len;		-> syscall(Sysmunmap, addr, len)}
+const mmap	= {addr, len, prot, flags, fd, off;	-> syscall(Sysmmap, addr, len, prot, flags, fd, off) castto(byte#)}
+
+/* time */
+const clock_getres = {clk, ts;	-> syscall(Sysclock_getres, clockid(clk), ts) castto(int32)}
+const clock_gettime = {clk, ts;	-> syscall(Sysclock_gettime, clockid(clk), ts) castto(int32)}
+const clock_settime = {clk, ts;	-> syscall(Sysclock_settime, clockid(clk), ts) castto(int32)}
+
+/* system information */
+const uname	= {buf;	-> syscall(Sysuname, buf) castto(int)}
+
+const sysctl = {mib, old, new
+	var mibp
+	var mibsz
+	var o
+	var oldp
+	var oldsz
+	var newp
+	var newsz
+	var ret
+
+	mibp = mib castto(byte#)
+	mibsz = mib.len castto(uint64)
+	o = old#
+	oldp = o castto(byte#)
+	oldsz = o.len castto(uint64)
+	newp = new castto(byte#)
+	newsz = new castto(uint64)
+
+	ret = syscall(Sys__sysctl, mibp, mibsz, oldp, &oldsz, newp, newsz) castto(int)
+
+	old# = o[:oldsz]
+	-> ret
+}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -238,7 +238,7 @@
     from = tystr(t);
     tybind(st, t);
     ht = mkht(tyhash, tyeq);
-    t = tyspecialize(t, ht);
+    t = tyspecialize(t, ht, st->delayed);
     htfree(ht);
     tyunbind(st, t);
     if (debugopt['u']) {
@@ -296,7 +296,7 @@
 }
 
 /* Look up the best type to date in the unification table, returning it */
-static Type *tysearch(Inferstate *st, Type *t)
+Type *tysearch(Type *t)
 {
     Type *lu;
     Stab *ns;
@@ -333,7 +333,7 @@
     Type *t;
     size_t i;
 
-    t = tysearch(st, orig);
+    t = tysearch(orig);
     st->ingeneric += isgeneric(orig);
     tyresolve(st, t);
     /* If this is an instantiation of a generic type, we want the params to
@@ -1434,7 +1434,7 @@
         checktraits(t->param, n->impl.type);
         ht = mkht(tyhash, tyeq);
         htput(ht, t->param, n->impl.type);
-        ty = tyspecialize(type(st, proto), ht);
+        ty = tyspecialize(type(st, proto), ht, st->delayed);
         htfree(ht);
 
         inferdecl(st, dcl);
@@ -1480,7 +1480,7 @@
 
     k = htkeys(s->ty, &n);
     for (i = 0; i < n; i++) {
-        t = tysearch(st, gettype(s, k[i]));
+        t = tysearch(gettype(s, k[i]));
         updatetype(s, k[i], t);
     }
     free(k);
@@ -1624,7 +1624,7 @@
     if (!tyflt)
         tyflt = mktype(-1, Tyfloat64);
 
-    t = tysearch(st, orig);
+    t = tysearch(orig);
     if (orig->type == Tyvar && hthas(st->delayed, orig)) {
         delayed = htget(st->delayed, orig);
         if (t->type == Tyvar)
@@ -1785,7 +1785,7 @@
 
     k = htkeys(s->ty, &n);
     for (i = 0; i < n; i++) {
-        t = tysearch(st, gettype(s, k[i]));
+        t = tysearch(gettype(s, k[i]));
         updatetype(s, k[i], t);
         tyfix(st, k[i], t);
     }
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -490,7 +490,7 @@
 
 /* specialize generics */
 Node *specializedcl(Node *n, Type *to, Node **name);
-Type *tyspecialize(Type *t, Htab *tymap);
+Type *tyspecialize(Type *t, Htab *tymap, Htab *delayed);
 Node *genericname(Node *n, Type *t);
 
 /* usefiles */
@@ -501,6 +501,7 @@
 
 /* typechecking/inference */
 void infer(Node *file);
+Type *tysearch(Type *t);
 
 /* debug */
 void dump(Node *t, FILE *fd);
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -31,12 +31,13 @@
  * parameters (type schemes in most literature)
  * replaced with type variables that we can unify
  * against */
-Type *tyspecialize(Type *t, Htab *tsmap)
+Type *tyspecialize(Type *t, Htab *tsmap, Htab *delayed)
 {
     Type *ret, *tmp;
     size_t i;
     Type **subst;
 
+    t = tysearch(t);
     if (hthas(tsmap, t))
         return htget(tsmap, t);
     switch (t->type) {
@@ -57,11 +58,11 @@
                 addtraits(tmp, subst[i]->traits);
                 htput(tsmap, subst[i], tmp);
             }
-            ret = mktyname(t->line, t->name, t->param, t->nparam, tyspecialize(t->sub[0], tsmap));
+            ret = mktyname(t->line, t->name, t->param, t->nparam, tyspecialize(t->sub[0], tsmap, delayed));
             ret->issynth = 1;
             htput(tsmap, t, ret);
             for (i = 0; i < t->nparam; i++)
-                lappend(&ret->arg, &ret->narg, tyspecialize(subst[i], tsmap));
+                lappend(&ret->arg, &ret->narg, tyspecialize(subst[i], tsmap, delayed));
             break;
         case Tystruct:
             ret = tydup(t);
@@ -77,7 +78,7 @@
             for (i = 0; i < t->nmemb; i++) {
                 tmp = NULL;
                 if (ret->udecls[i]->etype)
-                    tmp = tyspecialize(t->udecls[i]->etype, tsmap);
+                    tmp = tyspecialize(t->udecls[i]->etype, tsmap, delayed);
                 ret->udecls[i] = mkucon(t->line, t->udecls[i]->name, ret, tmp);
                 ret->udecls[i]->utype = ret;
                 ret->udecls[i]->id = i;
@@ -84,12 +85,21 @@
                 ret->udecls[i]->synth = 1;
             }
             break;
+        case Tyvar:
+            if (delayed && hthas(delayed, t)) {
+                ret = tydup(t);
+                tmp = htget(delayed, t);
+                htput(delayed, ret, tyspecialize(tmp, tsmap, delayed));
+            } else {
+                ret = t;
+            }
+            break;
         default:
             if (t->nsub > 0) {
                 ret = tydup(t);
                 htput(tsmap, t, ret);
                 for (i = 0; i < t->nsub; i++)
-                    ret->sub[i] = tyspecialize(t->sub[i], tsmap);
+                    ret->sub[i] = tyspecialize(t->sub[i], tsmap, delayed);
             } else {
                 ret = t;
             }
@@ -104,7 +114,7 @@
 static Type *tysubst(Type *t, Htab *tsmap)
 {
     if (hasparams(t))
-        return tyspecialize(t, tsmap);
+        return tyspecialize(t, tsmap, NULL);
     else
         return t;
 }
--- a/parse/type.c
+++ b/parse/type.c
@@ -297,6 +297,11 @@
 
     if (t->type != Tyname && t->type != Tyunres)
         return 0;
+    /*
+    if we have no arguments passed in, and we have parameters
+    we have a type of the form
+    type t(@a,...) = ...
+     */
     if (!t->narg)
         return t->nparam > 0;
     else
@@ -310,21 +315,46 @@
  * Checks if a type contains any type
  * parameers at all (ie, if it generic).
  */
-int hasparams(Type *t)
+int hasparamsrec(Type *t, Bitset *visited)
 {
     size_t i;
 
-    if (t->type == Typaram || isgeneric(t))
-        return 1;
-    for (i = 0; i < t->nsub; i++)
-        if (hasparams(t->sub[i]))
+    switch (t->type) {
+        case Typaram:
             return 1;
-    for (i = 0; i < t->narg; i++)
-        if (hasparams(t->arg[i]))
-            return 1;
+        case Tyname:
+        case Tyunres:
+            return isgeneric(t);
+        case Tystruct:
+            for (i = 0; i < t->nmemb; i++)
+                if (hasparamsrec(t->sdecls[i]->decl.type, visited))
+                    return 1;
+            break;
+        case Tyunion:
+            for (i = 0; i < t->nmemb; i++)
+                if (t->udecls[i]->etype && hasparamsrec(t->udecls[i]->etype, visited))
+                    return 1;
+            break;
+        default:
+            for (i = 0; i < t->nsub; i++)
+                if (hasparams(t->sub[i]))
+                    return 1;
+            break;
+    }
     return 0;
 }
 
+int hasparams(Type *t)
+{
+    Bitset *visited;
+    int r;
+
+    visited = mkbs();
+    r = hasparamsrec(t, visited);
+    bsfree(visited);
+    return r;
+}
+
 Type *tybase(Type *t)
 {
     assert(t != NULL);
@@ -414,9 +444,13 @@
     p += snprintf(p, end - p, "union ");
     for (i = 0; i < t->nmemb; i++) {
         name = namestr(t->udecls[i]->name);
-        ty = tystr(t->udecls[i]->etype);
-        p += snprintf(p, end - p, "`%s %s; ", name, ty);
-        free(ty);
+        if (t->udecls[i]->etype) {
+            ty = tystr(t->udecls[i]->etype);
+            p += snprintf(p, end - p, "`%s %s; ", name, ty);
+            free(ty);
+        } else {
+            p += snprintf(p, end - p, "`%s; ", name);
+        }
     }
     p += snprintf(p, end - p, ";;");
     return p - buf;
binary files a/test/genericmake /dev/null differ
--- /dev/null
+++ b/test/genericmake.myr
@@ -1,0 +1,20 @@
+use std
+
+type t(@ty) = union
+	`Some @ty
+	`None
+;;
+
+const make = {v
+	-> `Some v
+}
+
+const main = {
+	var x
+
+	x = make(123)
+	match x
+	| `std.Some v:	std.put("val = %i\n", v)
+	| `std.None:	std.die("Unreachable\n")
+	;;
+}
--- /dev/null
+++ b/test/genericuret.myr
@@ -1,0 +1,10 @@
+use std
+
+generic work = {val : @a
+	-> `std.Some val
+}
+
+const main = {
+	work(123)
+	std.exit(42)
+}
--- a/test/tests
+++ b/test/tests
@@ -86,6 +86,7 @@
 B genericrec	E	0
 # B genericchain	P	"val = 123" ## BUGGERED
 B genericmake	P	"val = 123"
+B genericuret	E	42
 B stdopt-some	E	42
 B stdopt-none	E	42
 B stdopt-mk	E	42