blueloveTH 1 年之前
父節點
當前提交
097a7fe94f
共有 6 個文件被更改,包括 89 次插入104 次删除
  1. 82 60
      amalgamate.py
  2. 1 1
      include/pocketpy/pocketpy_c.h
  3. 0 38
      scripts/genstub.py
  4. 3 2
      scripts/loc.py
  5. 2 2
      src/pocketpy_c.cpp
  6. 1 1
      src2/pocketpy_c.c

+ 82 - 60
amalgamate.py

@@ -1,78 +1,100 @@
+import re
+import shutil
 import os
+import sys
+import time
+from typing import List, Dict
 
 assert os.system("python prebuild.py") == 0
 
 with open("include/pocketpy/opcodes.h", "rt", encoding='utf-8') as f:
 	OPCODES_TEXT = '\n' + f.read() + '\n'
 
-pipeline = [
-	["config.h", "export.h", "_generated.h", "common.h", "memory.h", "vector.h", "str.h", "tuplelist.h", "namedict.h", "error.h", "any.h"],
-	["obj.h", "dict.h", "codeobject.h", "frame.h", "profiler.h"],
-	["gc.h", "vm.h", "ceval.h", "lexer.h", "expr.h", "compiler.h", "repl.h"],
-	["cffi.h", "bindings.h", "iter.h", "base64.h", "csv.h", "array2d.h", "dataclasses.h", "random.h", "linalg.h", "easing.h", "io.h", "modules.h"],
-	["pocketpy.h", "pocketpy_c.h"]
-]
-
-copied = set()
-text = ""
-
-import re
-import shutil
-import os
-import sys
-import time
+class Header:
+	path: str
+	content: str		# header+source (if exists)
+	dependencies: List[str]
+
+	def __init__(self, path: str):
+		self.path = path
+		self.dependencies = []
+
+		# get raw content
+		with open(f'include/pocketpy/{path}', 'rt', encoding='utf-8') as f:
+			self.content = f.read()
+		src_path = path.replace('.hpp', '.cpp').replace('.h', '.cpp')
+		if os.path.exists(f'src/{src_path}'):
+			with open(f'src/{src_path}', 'rt', encoding='utf-8') as f:
+				self.content += f'\n\n/* {src_path} */\n\n'
+				self.content += f.read()
+
+		# process raw content and get dependencies
+		self.content = self.content.replace('#pragma once', '')
+		def _replace(m):
+			path = m.group(1)
+			if path == 'opcodes.h':
+				return OPCODES_TEXT
+			if path != self.path:
+				self.dependencies.append(path)
+			return ''
+		
+		self.content = re.sub(
+			r'#include\s+"pocketpy/(.+)"\s*',
+			_replace,
+			self.content
+		)
+
+	def __repr__(self):
+		return f'Header({self.path!r}, dependencies={self.dependencies})'
+
+
+headers: Dict[str, Header] = {}
+
+for path in ['config.h', 'export.h', 'pocketpy.hpp', 'pocketpy_c.h']:
+	headers[path] = Header(path)
+
+directories = ['common', 'objects', 'interpreter', 'compiler', 'modules', 'tools']
+for directory in directories:
+	files = os.listdir(f'include/pocketpy/{directory}')
+	for file in sorted(files):
+		assert file.endswith('.h') or file.endswith('.hpp')
+		headers[f'{directory}/{file}'] = Header(f'{directory}/{file}')
+
+text = '''#pragma once
+
+/*
+ *  Copyright (c) 2024 blueloveTH
+ *  Distributed Under The MIT License
+ *  https://github.com/pocketpy/pocketpy
+ */'''
+
+while True:
+	for h in headers.values():
+		if not h.dependencies:
+			break
+	else:
+		if headers:
+			print(headers)
+			raise Exception("Circular dependencies detected")
+		break
+	print(h.path)
+	text += h.content
+	del headers[h.path]
+	for h2 in headers.values():
+		if h.path in h2.dependencies:
+			try:
+				h2.dependencies.remove(h.path)
+			except ValueError:
+				pass
 
 if os.path.exists("amalgamated"):
 	shutil.rmtree("amalgamated")
 	time.sleep(0.5)
 os.mkdir("amalgamated")
 
-def remove_copied_include(text):
-	text = text.replace("#pragma once", "")
-
-	def _replace(m):
-		key = m.group(1)
-		if key.startswith("pocketpy/"):
-			key = key[9:]
-		if key in ["user_config.h", "cJSONw.hpp"]:
-			return m.group(0)
-		if "opcodes.h" in key:
-			return OPCODES_TEXT
-		assert key in copied, f"include {key} not found"
-		return ""
-
-	text = re.sub(
-		r'#include\s+"(.+)"\s*',
-		_replace,
-		text
-	)
-	return text
-
-for seq in pipeline:
-	for j in seq:
-		print(j)
-		with open("include/pocketpy/"+j, "rt", encoding='utf-8') as f:
-			text += remove_copied_include(f.read()) + '\n'
-			copied.add(j)
-		j = j.replace(".h", ".cpp")
-		if os.path.exists("src/"+j):
-			with open("src/"+j, "rt", encoding='utf-8') as f:
-				text += remove_copied_include(f.read()) + '\n'
-				copied.add(j)
-
 # use LF line endings instead of CRLF
 with open("amalgamated/pocketpy.h", "wt", encoding='utf-8', newline='\n') as f:
-	final_text = \
-r'''/*
- *  Copyright (c) 2024 blueloveTH
- *  Distributed Under The MIT License
- *  https://github.com/pocketpy/pocketpy
- */
-
-#ifndef POCKETPY_H
-#define POCKETPY_H
-''' + text + '\n#endif // POCKETPY_H'
-	f.write(final_text)
+	f.write(text)
 
 shutil.copy("src2/main.cpp", "amalgamated/main.cpp")
 with open("amalgamated/main.cpp", "rt", encoding='utf-8') as f:

+ 1 - 1
include/pocketpy/pocketpy_c.h

@@ -8,7 +8,7 @@ extern "C" {
 #include <stdbool.h>
 #include <stdint.h>
 
-#include "export.h"
+#include "pocketpy/export.h"
 
 typedef struct pkpy_vm_handle pkpy_vm;
 typedef int (*pkpy_CFunction)(pkpy_vm*);

+ 0 - 38
scripts/genstub.py

@@ -1,38 +0,0 @@
-import os
-
-with open('include/pocketpy/pocketpy_c.h') as f:
-    lines = f.readlines()
-
-a = []
-for line in lines:
-    if line.startswith("PK_EXPORT"):
-        _, ret, *body = line.split()
-    else:
-        continue
-    body = ' '.join(body)
-    assert body.endswith(";")
-    body = body[:-1]
-
-    if '(pkpy_vm*' in body:
-        body = body.replace('(pkpy_vm*', '(pkpy_vm* vm')
-
-    if ret == 'void':
-        mock_string = ''
-    else:
-        mock_string = ' '*4 + ret + ' returnValue;\n    return returnValue;'
-
-    a.append(
-        ret + ' ' + body + ' {\n' + mock_string + '\n}\n'
-    )
-
-# use LF line endings instead of CRLF
-with open('src2/pocketpy_c.c', 'wt', encoding='utf-8', newline='\n') as f:
-    f.write('''
-#include "pocketpy_c.h"
-
-#ifdef _WIN32
-#pragma warning(disable: 4700)
-#endif
-            
-''')
-    f.write('\n'.join(a))

+ 3 - 2
scripts/loc.py

@@ -4,6 +4,8 @@ def get_loc(path):
     loc = 0
     with open(path, "rt", encoding='utf-8') as f:
         loc += len(f.readlines())
+    path = path.replace('\\', '/')
+    print(f'{path}: {loc}')
     return loc
 
 def get_loc_for_dir(path):
@@ -11,9 +13,8 @@ def get_loc_for_dir(path):
     loc_ex = 0
     for root, dirs, files in os.walk(path):
         for file in files:
-            if file.endswith('.h') or file.endswith('.cpp'):
+            if file.endswith('.h') or file.endswith('.cpp') or file.endswith('.hpp'):
                 _i = get_loc(os.path.join(root, file))
-                print(f"{file}: {_i}")
                 if file.startswith('_'):
                     loc_ex += _i
                 else:

+ 2 - 2
src/pocketpy_c.cpp

@@ -1,7 +1,7 @@
 #ifndef PK_NO_EXPORT_C_API
 
-#include "pocketpy.h"
-#include "pocketpy_c.h"
+#include "pocketpy/pocketpy.hpp"
+#include "pocketpy/pocketpy_c.h"
 
 #include <iostream>
 

+ 1 - 1
src2/pocketpy_c.c

@@ -1,5 +1,5 @@
 
-#include "pocketpy_c.h"
+#include "pocketpy/pocketpy_c.h"
 
 #ifdef _WIN32
 #pragma warning(disable: 4700)